【问题标题】:Lodash: _.forEach with functionLodash: _.forEach 带函数
【发布时间】:2015-09-03 20:40:30
【问题描述】:

我正在尝试将 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);

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

我希望在 for each 和 inner 函数完成后调用回调。

【问题讨论】:

  • 你应该使用async.map

标签: javascript lodash


【解决方案1】:

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

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

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

【讨论】:

  • 假设一个现代 JavaScript 引擎(或一个好的 polyfill),这绝对是更易读的方法之一!
【解决方案2】:

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

当然,有包装器结构可以做这样的事情,但我更愿意解释它是如何工作的。查看dfsq's answer,了解有关其中一种包装器(称为承诺)的更多详细信息。

另请注意,异步操作可能会乱序完成。 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);
    });
});

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

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

results.push({id: id, error: null, value: result});

【讨论】:

    猜你喜欢
    • 2016-01-25
    • 2016-01-23
    • 2014-08-12
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 2015-06-15
    • 2014-02-08
    相关资源
    最近更新 更多