2017-10-05 71 views
0

所以我意识到今天我一直迭代通过使用递归和嵌套承诺严重承诺,并希望学习如何正确使用Q.all()。我正在尝试遍历一系列异步函数并等待所有这些函数在继续之前解析。在当前的实现中,Q.all立即返回而不用等待解决的承诺。这里是我的迭代函数return q.all()没有等待解析,除非包装在deferred.resolve

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); 

} 

和这里代码的异步功能是调用:

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; 
} 

如果我改变实现像这样它的工作原理完全罚款:

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 
} 

从我所知道的情况来看,这是一种不正确的方式来实现这一点,但我希望在第一时间做到正确。如果有任何帮助,这里是我打电话给updateNewReleasePlaylists函数进行测试的地方。

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(); 
        }) 
      }) 
    }) 

感谢您的提前帮助。

+0

你是异步的(在'find'回调!)推入'promises'数组,然后立即在'Q.all'中使用它。当然,它在那里是空的,并立即满足。你应该适当地提出'User.find',并且在'then'回调中使用数组和'Q.all' * only *! – Bergi

回答

1

如果promises数组为空,那么得到回报似乎是正确的,因为没有什么可以等待。当find()完成时,由于它的异步性质,promises数组仍然是空的,因为函数(err,users)还没有被调用。所以,如果我正确地说find()是异步的,你应该返回整个User.find()或promise-wrap(如果需要的话)并返回它。

+0

是的,User.find是异步的。那么在这个特定的用例中,将Q.all包装在deferred.resolve()中是否可以?我在网上看到的很多例子都没有这样做。 – Ryan

+0

我没有看到任何错误的承诺包装。有些库可以做到这一点。如果我帮助,请将我的答案标记为已接受。 CHEARS – JohnPan