2012-05-04 14 views
5

Necesito ayuda con la naturaleza asincrónica de node.js. Tengo un bucle for, que recopila datos de la base de datos. "resultado" es una matriz, que luego debería devolverse a la función principal.Devolución de llamada después de terminar for-loop en node.js

user_collection.findOne({ 
      _id : uid 
     }, function(error, user) { 
      if(error) 
       callback(error) 
      else { 
       for(var j = 0; j < user.contacts.length; j++) { 
        if(user.contacts[j].accepted == 'true') { 
         user_collection.findOne({ 
          _id : user.contacts[j].contactId 
         }, function(error, user) { 
          result.push(user); 
         }) 
        } 
       } 
       callback(null, result); // This callback executes before the for-loop ends, ofc 
      } 
     }); 

¿Cómo puedo garantizar que la devolución de llamada se ejecute una vez finalizado el ciclo?

+0

Versión de trabajo con async: 'user_collection.findOne ({ \t \t \t \t _id: userId \t \t \t}, la función (error, el usuario) { \t \t \t \t si (error) \t \t \t \t \t de devolución de llamada (error) \t \t \t \t else { \t \t \t \t \t async.forEach (user.contac ts, función (contacto, devolución de llamada) { \t \t \t \t \t \t console.log (contacto); \t \t \t \t \t \t si (== contact.accepted 'verdadero') { \t \t \t \t \t \t \t user_collection.findOne ({ \t \t \t \t \t \t \t \t _id: contact.contactId \t \t \t \t \t \t \t}, fu ncio (error, de contacto) { \t \t \t \t \t \t \t \t result.push (contacto); \t \t \t \t \t \t \t \t callback(); \t \t \t \t \t \t \t}) \t \t \t \t \t \t} \t \t \t \t \t}, la función (error) {devolución de llamada (error, resultado)}) \t \t \t \t} \t \t \t}); ' – johnny

Respuesta

10

Es posible que desee considerar el uso de una biblioteca de ayuda como asíncrono https://github.com/caolan/async

Ayuda a mantener el código más consistente ..

En su caso, usted puede mirar en el forEach() método

forEach(arr, iterator, callback) 

Se llama al iterador con un elemento de la lista y una devolución de llamada cuando finaliza.

de partida de los pruebas de unidad para los ejemplos

https://github.com/caolan/async/blob/master/mocha_test/each.js

+0

¡Gracias! ¡Lo estoy usando ahora y funciona! – johnny

0

Con v1.5.2 de Async.js, Es each.

each(arr, iterator, [callback]) 

arr - Una matriz para iterar sobre.
iterador (artículo, devolución de llamada) - Una función para aplicar a cada elemento en arr.
devolución de llamada (err) - Opcional. Una devolución de llamada que se llama cuando todas las funciones del iterador han terminado, o se produce un error.

1

Usando ES6 Promises (una biblioteca promesa se puede utilizar para navegadores antiguos):

Proceso de todas las solicitudes que garantizan la ejecución síncrona (por ejemplo 1 a continuación 2 a continuación, 3)

function asyncFunction (item, cb) { 
    setTimeout(() => { 
    console.log('done with', item); 
    cb(); 
    }, 100); 
} 

let requests = [1, 2, 3].reduce((promiseChain, item) => { 
    return promiseChain.then(new Promise((resolve) => { 
     asyncFunction(item, resolve); 
    })); 
}, Promise.resolve()); 

requests.then(() => console.log('done')) 

Proceso de todas las solicitudes asíncronas sin "sincrónica" ejecución (2 puede terminar más rápido que 1)

let requests = [1,2,3].map((item) => { 
    return new Promise((resolve) => { 
     asyncFunction(item, resolve); 
    }); 
}) 

Promise.all(requests).then(() => console.log('done')); 

lo hice en ese camino

Promise.all(body.schedules.map(function(scheduleId) { 
     return new Promise(function(resolve, reject) { 
      return scheduleSchema.findOneAndRemove({ 
        _id: scheduleId 
       }) 
       .then(function() { 
        logSchema.insert({ 
         userId: req.user.id, 
         actId: constants.LOG_SCHEDULE_DELETE.id, 
         extData: scheduleId 
        }); 
        resolve(); 
       }) 
       .catch(function(err) { 
        reject(err); 
       }); 
     }); 
    })).then(function() { 
     return res.json({ 
      code: constants.SUCCESS_CODE 
     }); 
    }).catch(function(err) { 
     return res.json(constants.DATABASE_ERROR); 
    }); 

El último ejemplo

function callback (result) { console.log('all done'); } 

[1, 2, 3].forEach((item, index, array) => { 
    asyncFunction(item,() => { 
    if (index === array.length - 1) { 
     callback(); 
    } 
    }); 
}); 

Esto no garantiza que la devolución de llamada se ejecutará después de que todos los artículos se procesan. Solo garantiza que la devolución de llamada se ejecutará después de procesar el último elemento.

More information

Michael.

Cuestiones relacionadas