在node.js中完成for循环后的回调

时间:2012-05-04 11:50:19

标签: javascript node.js callback

我需要一些有关node.js异步性质的帮助。我有一个for循环,它从数据库中收集数据。 “result”是一个数组,然后应该返回到main函数。

user_collection.findOne({
            _id : uid
        }, function(error, user) {
            if(error)
                callback(error)
            else {
                for(var j = 0; j < user.contacts.length; j++) {
                    if(user.contacts[j].accepted == 'true') {
                        user_collection.findOne({
                            _id : user.contacts[j].contactId
                        }, function(error, user) {
                            result.push(user);
                        })
                    } 
                }
                callback(null, result);  // This callback executes before the for-loop ends, ofc
            }
        });

如何在循环结束后确保回调执行?

3 个答案:

答案 0 :(得分:11)

您可能需要考虑使用辅助库,例如 async https://github.com/caolan/async

它有助于保持代码更加一致..

在您的情况下,您可以查看forEach()方法

forEach(arr, iterator, callback)

使用列表中的项目和完成时的回调来调用迭代器。

查看单元测试以获取示例

https://github.com/caolan/async/blob/master/mocha_test/each.js

答案 1 :(得分:1)

使用ES6承诺 (promise库可用于旧版浏览器):

处理保证同步执行的所有请求(例如1然后2然后3)

function asyncFunction (item, cb) {
  setTimeout(() => {
    console.log('done with', item);
    cb();
  }, 100);
}

let requests = [1, 2, 3].reduce((promiseChain, item) => {
    return promiseChain.then(new Promise((resolve) => {
      asyncFunction(item, resolve);
    }));
}, Promise.resolve());

requests.then(() => console.log('done'))

处理所有异步请求而不执行“同步”(2可能比1快完成)

let requests = [1,2,3].map((item) => {
    return new Promise((resolve) => {
      asyncFunction(item, resolve);
    });
})

Promise.all(requests).then(() => console.log('done'));

我是这样做的

Promise.all(body.schedules.map(function(scheduleId) {
        return new Promise(function(resolve, reject) {
            return scheduleSchema.findOneAndRemove({
                    _id: scheduleId
                })
                .then(function() {
                    logSchema.insert({
                        userId: req.user.id,
                        actId: constants.LOG_SCHEDULE_DELETE.id,
                        extData: scheduleId
                    });
                    resolve();
                })
                .catch(function(err) {
                    reject(err);
                });
        });
    })).then(function() {
        return res.json({
            code: constants.SUCCESS_CODE
        });
    }).catch(function(err) {
        return res.json(constants.DATABASE_ERROR);
    });

最后一个例子

function callback (result) { console.log('all done'); }

[1, 2, 3].forEach((item, index, array) => {
  asyncFunction(item, () => {
    if (index === array.length - 1) {
      callback();
    }
  });
});

这并不能保证在处理完所有项目后都会执行回调。它只保证在最后一个项目处理后执行回调。

More information

迈克尔。

答案 2 :(得分:0)

使用Async.js的v1.5.2,它是each

each(arr, iterator, [callback])

arr - 要迭代的数组。
迭代器(项目,回调) - 应用于arr中每个项目的功能。
回调(错误) - 可选。 所有迭代器函数完成或发生错误时调用的回调