Lodash:_.forEach with function

Sta*_*hil 11 javascript lodash

我试图使用lodash forEach方法与嵌套函数调用mongo数据库.

var jobs = [];
_.forEach(ids, function(id) {
    JobRequest.findByJobId(id, function(err, result) {
        if(err) callback(err);
        jobs.push(result);
    });
});

callback(null, jobs);
Run Code Online (Sandbox Code Playgroud)

我遇到了问题,因为forEach和回调将在调用内部函数之前运行.我该如何解决这个问题?

我希望在每个和内部函数完成后调用回调.

dfs*_*fsq 12

另一种方法是将所有内容包装到promises中,在这种情况下,作业结果将按正确的顺序推送到数组中:

var promises = ids.map(function(id) {
    return new Promise(function(resolve, reject) {
        JobRequest.findByJobId(id, function (err, result) {
            if (err) reject(err);
            resolve(result);
        });
    });
});

Promise.all(promises).then(function(jobs) {
    callback(null, jobs);
}, callback);

// or shorter: Promise.all(promises).then(callback.bind(null, null), callback);
Run Code Online (Sandbox Code Playgroud)

请注意,您还需要在JobRequest.findByJobId请求失败时处理潜在的情况,使用promises非常简单:只需将callback错误回调传递给Promise.all.


jwu*_*ler 8

JobRequest.findByJobId是一个异步操作.您无法阻止JavaScript中的异步操作,因此您需要通过计数手动同步.示例(为简洁起见省略了错误处理):

var results = [];
var pendingJobCount = ids.length;

_.forEach(ids, function(id) {
    JobRequest.findByJobId(id, function(err, result) {
        results.push(result);
        if (--pendingJobCount === 0) callback(null, results);
    });
});
Run Code Online (Sandbox Code Playgroud)

当然,还有用于执行此类操作的包装器构造,但我更喜欢解释它实际上是如何工作的.查看dfsq的答案,了解有关其中一个包装器(称为promises)的更多详细信息.

另请注意,异步操作可能无序完成.中相应的顺序results阵列将不一定匹配的顺序ids数组.如果您需要连接这些信息,您需要自己跟踪它,例如通过在地图而不是数组中收集结果:

var results = {};
var pendingJobCount = ids.length;

_.forEach(ids, function(id) {
    JobRequest.findByJobId(id, function(err, result) {
        results[id] = result;
        if (--pendingJobCount === 0) callback(null, results);
    });
});
Run Code Online (Sandbox Code Playgroud)

此示例假定您的ids数组中没有重复项.将覆盖重复键的结果.

通过在结果中插入其他信息,错误处理的工作方式类似.另一个例子:

results.push({id: id, error: null, value: result});
Run Code Online (Sandbox Code Playgroud)