2016-05-17 9 views
1

Ich versuche, eine Versprechen-Funktion zu machen, die ein Array von E-Mails liest, dann die Benutzer-ID findet und sie in ein anderes Array verschiebt. Das Problem ist, dass meine Q.all Funktion ausgeführt wird, bevor _.forEach fertig ist. Check it out:Q.all läuft vorher forEach

var deferred = Q.defer(), 
    promises = [], 
    _ = require('lodash'); 

_.forEach(users, function(user) { 
    User.findOne({ 
     username: user 
    }, function(err, member) { 
     if (err) 
     console.log(err); 

     var memberId = member._id; 
     promises.push(members.push(memberId)); 
    }); 
}); 

Q.all(promises) 
    .then(function(promises) { 
    deferred.resolve(promises); 
    console.log(promises); // This always returns -> [] 
    }) 
    .catch(function(err) { 
    deferred.reject(err); 
    }); 

return deferred.promise; 

Also jedes Mal wenn ich versuche, meine Reihe von Versprechungen console.log, erhalte ich ein leeres Array. Ich habe sogar versucht, JavaScript native forEach Funktion zu verwenden, aber es hat nicht funktioniert.

Ist forEach das Problem oder Q.all ist nicht die geeignete Funktion für diesen Fall?

Vielen Dank im Voraus.


GELöST (Lösung vorgeschlagen von Robert Moskal)

In meinem Fall die async Bibliothek zusammen mit Q.defer() das Problem gelöst.

var async = require('async'), 
    deferred = Q.defer(); 

async.map(users, function(each, done){ 
    User.findOne({ 
    username: each 
    }, function(err, member) { 
     if (err) 
     console.log(err); 
     done(null, member._id); 
     }); 
    }, function(err, results){ 
    if (err) 
     deferred.reject(err); 
    deferred.resolve(results); 
}); 

return deferred.promise; 

Antwort

1

Ihr Problem ist, dass die User.findOne Funktion asynchron ist, so dass die Q.all Funktion ausgeführt wird, bevor irgendetwas auf dem Versprechen Array geschoben wird.

Es ist normalerweise besser, Callbacks und Versprechungen nicht zu mischen. Wie für die Befestigung. Wenn das ein Mungo-Modell ist, dann könnte man das Versprechen basierte Version von FindOne verwenden:

var deferred = Q.defer(), 
    promises = [], 
    _ = require('lodash'); 

_.forEach(users, function(user) { 
    promises.push(User.findOne({ 
     username: user})); 
}); 

Q.all(promises) 
    .then(function(promises) { 
    deferred.resolve(promises); 
    console.log(promises); // This always returns -> [] 
    }) 
    .catch(function(err) { 
    deferred.reject(err); 
    }); 

return deferred.promise; 

Oder Sie könnten von der Asynchron-Bibliothek benutzen, die wie folgt aussehen könnte:

async.map(users, function(each, done){ 

User.findOne({ 
     username: user 
    }, function(err, member) { 
     if (err) 
     console.log(err); 
     done(null, member._id); 

    }); 
}, 
function(err, results){ 
    //results holds your array of ids 
    } 
); 
+0

Async Bibliothek mein Problem gelöst. Vielen Dank! – Matheuz