2017-10-05 3 views
0

So realisierte ich heute habe ich durch Versprechen mit Hilfe von Rekursion und verschachtelte Versprechen schlecht durchlaufen und wollte lernen, wie man Q.all() richtig zu verwenden. Ich versuche, eine Reihe von asynchronen Funktionen zu durchlaufen und darauf zu warten, dass alle auflösen, bevor ich fortfahre. In dieser aktuellen Implementierung wird Q.all sofort zurückgegeben, ohne auf die Lösung der Versprechungen zu warten. Hier ist mein Code für die Iterieren Funktionreturn q.all() nicht warten auf Auflösung, wenn in deferred.resolve eingewickelt

var updateNewReleasePlaylists = function() { 
    var self = this; 
    var promises = []; 
    var deferred = Q.defer(); 

    // query for all users who have new releases 
    User.find({ 
      $and: [{ 
        'new_releases': { 
         $exists: true, 
         $ne: [] 
        } 
       }, 
       { 
        'refresh_token': { 
         $exists: true 
        } 
       } 
      ] 
     }, 'new_releases', 
     function (err, users) { 
      if (err) { 
       throw new Error(err); 
      } 
      for (var i = 0; i < users.length; i++) { 
       console.log('when?') 
       promises.push(updatePlaylist(users[i])); 
      } 
     }); 
return Q.all(promises); 

} 

und das hier ist die Asynchron-Funktion es ruft:

function updatePlaylist(user) { 
    var deferred = Q.defer(); 
    User.findOne({'_id': user._id}, function(err, user) { 
     if (err) { 
      deferred.reject(err); 
     } 
     console.log(user); 
     deferred.resolve(); 
    }) 
    return deferred.promise; 
} 

Wenn ich die Implementierung ändern wie so funktioniert es völlig in Ordnung:

var updateNewReleasePlaylists = function() { 
    var self = this; 
    var promises = []; 
    var deferred = Q.defer(); 

    // query for all users who have new releases 
    User.find({ 
      $and: [{ 
        'new_releases': { 
         $exists: true, 
         $ne: [] 
        } 
       }, 
       { 
        'refresh_token': { 
         $exists: true 
        } 
       } 
      ] 
     }, 'new_releases', 
     function (err, users) { 
      if (err) { 
       throw new Error(err); 
      } 
      for (var i = 0; i < users.length; i++) { 
       console.log('when?') 
       promises.push(updatePlaylist(users[i])); 
      } 
      deferred.resolve(Q.all(promises)); // DIFFERENT 
     }); 
     return deferred.promise; // DIFFERENT 
} 

Von dem, was ich sagen kann, ist dies eine falsche Art, dies zu implementieren, und ich möchte es beim ersten Mal richtig machen. Wenn es Hilfe ist, hier ist, wo ich die updateNewReleasePlaylists Funktion zum Testen aufrufen.

it('updateNewReleasePlaylists should properly resolve after all users playlists have been updated', function (done) { 
     this.timeout(60000); 
     testHelper.stageSpotifyUser(20) 
      .then(testHelper.stageSpotifyUser(20)) 
      .then(testHelper.stageSpotifyUser(20)) 
      .then(function() { 
       playlist.updateNewReleasePlaylists() 
        .then(function (promises) { 
         console.log(promises.length); 
         console.log('should be after'); 
         done(); 
        }) 
      }) 
    }) 

Vielen Dank für Ihre Hilfe im Voraus der Zeit.

+0

Sie sind asynchron (in der 'find' Callback!) Drücken auf die' Versprechen' Array, aber dann sofort in 'Q.all' verwenden. Natürlich ist es dort leer und erfüllt sich sofort. Sie sollten "User.find" richtig promiden und das Array und 'Q.all' * only * in einem' then' Callback verwenden! – Bergi

Antwort

1

Wenn das Array der Versprechen leer ist, dann scheint es richtig, Ihre Rückkehr zu bekommen, weil es nichts zu warten gibt. Wenn find() aufgrund seiner asynchronen Natur beendet wird, ist das Array arrives immer noch leer, da die Funktion (err, users) noch nicht aufgerufen wurde.

Also, wenn ich richtig bin über find() async, sollten Sie die gesamte User.find() oder Versprechen-Wrap bei Bedarf zurückgeben und das zurückgeben.

+0

Yeah User.find ist asynchron. Also in diesem speziellen Anwendungsfall ist es in Ordnung, Q.all in eine deferred.resolve() zu verpacken? Viele der Beispiele, die ich online gesehen habe, tun das nicht. – Ryan

+0

Ich sehe nichts falsches mit Versprechen Verpackung. Es gibt Bibliotheken, die das tun. Bitte markieren Sie meine Antwort als akzeptiert, wenn ich geholfen habe. Chears – JohnPan

Verwandte Themen