Foro de elhacker.net

Programación => Desarrollo Web => Mensaje iniciado por: [u]nsigned en 6 Julio 2020, 00:26 am



Título: (RESUELTO)[Mongoose] Me estoy volviendo loco, como hacer esto?
Publicado por: [u]nsigned en 6 Julio 2020, 00:26 am
Hola, resulta que toda mi vida use Node junto con MySQL, pero ahora se me dio por usar Mongo con Mongoose en un proyecto, y me estoy volviendo loco con algo.

Tengo dos modelos. Uno es de clientes y otro de Application(que serian las veces que dicho cliente se aplico mi producto). Los 'application' tienen un campo cliente que hace referencia al id del cliente que lo compro. Yo pensaba que luego podría emular los joins de mysql, pero resulta que si no existe un un articulo para cada cliente entonces el populate no funciona, probe hacerlo con virtual, pero por lo que entendi de la doc de mongoose no funciona.

Entonces se me ocurrió hacerlo a la antigua, como trabajaba con PHP.

Primero leo todos los clientes de mi DD.BB. Y luego recorro el array con un foreach y para cada uno busco en la colección Application si existe una para dicho cliente. Pero no logro dominar la asincronia.

Lo que yo espero es que en consola se muestre algo como
Citar
00000000000000000 0000000000000000000
00000000000000000 0000000000000000000
00000000000000000 Sin Aplicaciones
00000000000000000 Sin Aplicaciones
00000000000000000 Sin Aplicaciones
00000000000000000 0000000000000000000
00000000000000000 0000000000000000000

Y luego de eso se imprima  console.log('C', C); Pero resulta que siempre se imprime antes de terminar el bucle forEach. Tengo los await en todas las llamadas a mongoose, por lo que la logica me dice que deberian ejecutarse todas las sentencias y finalmente imprimir en consola el contenido de C.

Me estoy volviendo loco, estoy a nada de volver a PHP (js y su p*ta asincronía)  :xD

Código
  1. router.get('/', async (req, res, next) => {
  2.    const clientes = await Client.find();
  3.  
  4.    var C = [];
  5.  
  6.    //Traigo la ultima aplicacion si es que tiene
  7.    await clientes.forEach(async (cliente, index) => {
  8.        const application = await Application.findOne({
  9.            cliente: cliente._id,
  10.        });
  11.  
  12.        if (application) {
  13.            console.log(cliente._id, application._id);
  14.        } else {
  15.            console.log(cliente._id, 'Sin Aplicaciones');
  16.        }
  17.    });
  18.  
  19.    console.log('C', C);
  20.  
  21.    return res.json({ ok: true, clientes });
  22. });


Título: Re: [Mongoose] Me estoy volviendo loco, como hacer esto?
Publicado por: MinusFour en 6 Julio 2020, 01:24 am
No se mucho de moongose, pero si clientes es un arreglo y forEach ahí es Array.prototype.forEach entonces es probable que no vengan en orden. Array.prototype.forEach no regresa nada, por ende, hacer await sobre el resultado no hace nada tampoco. Lo único que el método haría es correr la función async contra cada entrada del arreglo. No hace nada con los resultados.

Ahora, si usaras Array.prototype.map en su lugar tendrías como resultado un arreglo de promesas, porque este método si regresa los resultados de la función que corres.  Con ese arreglo de promesas lo puedes pasar a Promise.all para obtener otra promesa que se cumple cuando todas las promesas se llegan a cumplir.

Código
  1. await Promise.all(arreglo.map(async() => {}));


Título: Re: [Mongoose] Me estoy volviendo loco, como hacer esto?
Publicado por: [u]nsigned en 6 Julio 2020, 01:43 am
Muchisimas gracias me salvaste el dia!!  ;-) ;-)