withEach的简单承诺

时间:2016-04-26 08:27:58

标签: javascript node.js mongoose promise q

我正在尝试使用Promise来等待异步forEach:

var forEachMatch = function(matches) {
    var deferred = Q.defer();
    matches.forEach(function(match) {
        var messages = Message.find({'matchid': match._id}, function(err,messages) {
            if(err)
                console.log(err);
            else
                console.log(match._id);
        });
    });
    return deferred.promise;
};

在这里使用:

forEachMatch(matches, function() {
    console.log("DONE");
    res.status(200).json({
        bob,
        matches: matches,
    });
});

我的控制台输出如下:所有match._id都已打印,但DONE从未打印过。

有什么想法解决它吗?我从节点和承诺开始,所以我当然忘记了一些东西,但我没有看到。

感谢您的回答。

修改

最终解决方案,感谢Alexander Mac:

var forEachMatch = function(matches) {
  var promises = matches.map(match => {
    return Message
    .find({'matchid': match._id})
    .populate({
      path: 'fromUser toUser',
      select: 'id firstname'
    })
    .then(messages => [match, messages])
    .catch(err => {
      console.log("Error in forEachMatch");
      return [match, null];
    });
  });
  return Q.all(promises);
}

forEachMatch(matches)
  .then(messagesByMatch => {
    res.status(200).json({
      user,
      messagesByMatch: messagesByMatch
    });
  });

3 个答案:

答案 0 :(得分:1)

在你的情况下,匹配更好地使用Q.all,它接受​​一组承诺或值:

var forEachMatch = function(matches) {
  var promises = matches.map(match => {
    return Message
      .find({'matchid': match._id})
      .then(messages => [match, messages]);
  });
  return Q.all(promises);
}

forEachMatch(matches)
  .then(results => {
    console.log("DONE", results);
    res.status(200).json({
      bob,
      matches: matches,
  });
});

https://github.com/kriskowal/q/wiki/API-Reference#promiseall

答案 1 :(得分:1)

您正在退回延期承诺,并且该承诺未得到解决或拒绝。请尝试以下方法:

CustomHandler

};

然后调用者将成为

var forEachMatch = function(matches) {
var deferred = Q.defer();
matches.forEach(function(match) {
    var messages = Message.find({'matchid': match._id}, function(err,messages) {
        if(err)
            deferred.reject(err);
        else
            deferred.resolve(match._id);
    });
});
return deferred.promise;

答案 2 :(得分:0)

您从未调用promise.rejectpromise.reject方法。此外,还承诺异步操作,而forEach不是。

这是一个肮脏的修复:

 var forEachMatch = function(matches) {
  var deferred = Q.defer();
  // make the foreach asynchronous
  setTimeout(function() {
    matches.forEach(function(match) {
      // do stuff
    });
    // notify end
    deferred.resolve();
  }, 0);

  return deferred.promise;
};

// use .then
forEachMatch(matches).then(function() {
  console.log("DONE");
});