javascript - Promises 和 Q - 使用 forEach 完成一系列函数

标签 javascript mongodb promise q

对如何最好地写这个有点困惑 - 希望这个描述是清楚的。

我有一个 forEach 函数,在其中我遍历一些 JS 对象数据,并且对于每个项目我执行一个函数:

found.forEach(function(item) {
      processData(item['userID']);
});

在此 processData 函数中,我使用 MongoDB find() 调用。

var processData = function(userIDSelected) {

    User.find( {_id: userIDSelected},
           {gender: 1, country:1}, function(req, foundUser) {
            processUserInfo(foundUser[0]['gender']);
    });
}

我遇到的问题是,考虑到每个调用将依次运行 processUserInfo,我如何等待 forEach 中的所有内容完成。

我考虑过使用 Q 库和 Q.all,但是这不起作用。

是否有一个 Q 函数等待长链中的所有内容完成?

谢谢

最佳答案

Q.all :

Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected.

Q.allSettled :

Returns a promise that is fulfilled with an array of promise state snapshots, but only after all the original promises have settled, i.e. become either fulfilled or rejected.

所以你会做三件事:

  1. 修改 processData 以及可能的对 MongoDB 的调用,以便最终 processData 返回异步操作的 promise 。 (抱歉,我对 MongoDB 不熟悉。 Alnitak says 在现代版本中,如果您不提供回调,MongoDB 将返回一个 promise (很好!)。否则, this question and its answers may help 返回回调的 promise -基于 API。)

  2. 使用 map 而不是 forEach 来获取结果 Promise 的数组。

  3. 对该 Promise 数组使用 Q.allQ.allSettled

如果 User.find 在未指定回调的情况下返回一个 Promise,则 #1 看起来类似,如下所示:

var processData = function(userIDSelected) {

    return User.find(
           {_id: userIDSelected},
           {gender: 1, country:1}
    ).then(function(req, foundUser) { // <== Check these args with the MongoDB docs!
        return processUserInfo(foundUser[0]['gender']);
    });
};

如果没有,您可以使用 Q.defer 自行完成:

var processData = function(userIDSelected) {
    var d = Q.defer();
    User.find(
           {_id: userIDSelected},
           {gender: 1, country:1},
           function(req, foundUser) {
        processUserInfo(foundUser[0]['gender']);
        d.resolve(/*...data could go here...*/); // You'd use d.reject() if there were an error
    });
    return d.promise;
};

下面是 2 和 3 的样子:

Q.all(found.map(function(item) { // Or Q.allSettled
    return processData(item);
}))
.then(...)
.catch(...);

如果processData仅使用其第一个参数(忽略任何额外的参数),您可以放弃中间函数:

Q.all(found.map(processData)) { // Or Q.allSettled
.then(...)
.catch(...);

...但是如果processData忽略额外的参数,因为map将向其传递三个(值、索引和数组)。

关于javascript - Promises 和 Q - 使用 forEach 完成一系列函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35409319/

相关文章:

javascript - 合并在一个文件中时,缩小的 Javascript 不起作用

javascript - bootstrapTable() 方法在表数据下留下空白空间

node.js - 有条件更新,取决于匹配的字段

mongodb - Redis 比 mongoDB 快多少?

javascript - 为什么我收到 UnhandledPromiseRejectionWarning : Unhandled promise rejection?

javascript - REST-api 异步查询的随机结果

javascript - 禁用webapp的ios5通知中心下拉

javascript - 数组极端情况下的二进制搜索

node.js - MongooseJS - 具有过滤和排序功能

javascript - 如何在for循环中循环 promise 并在满足条件时中断