如何使用Q.js将Array.forEach转换为异步



我需要为数组的所有项动态执行一个函数,但Array.forEach按顺序执行,我需要异步执行。

items.forEach(function(item) {
doSomething(item);
});

我试试这个:

var promises = [];
items.forEach(function(item) {
var promise = function() {
return Q.fcall(function() {
doSomething(item);
});
};
promises.push(promise());
});
Q.all(promises).then(function () {
otherFunction(datacontext.mainList); //use datacontext.mainList filled.
});

但是执行总是按顺序进行的,我需要并行执行。

doSomething(item)方法:

function doSomething(item) {
var children = getChildren(item); //get data from local with manager.executeQueryLocally
var total = getTotal(children); //simple calculations
datacontext.mainList.push({
name: item.firstName() + ' ' + item.lastName(),
total: total
});
}

请帮帮我。

这个答案假设doSomething本身就是一个异步操作。这意味着它将不得不屈服于事件循环,并至少每隔一段时间等待另一个事件。如果doSomething是同步的,那么异步编写它没有任何好处。

在复合异步作业领域中,有串行和并行的变体。串行模型导致作业(n+1)仅在作业(n)完成之后才开始。并行模型最初启动所有作业,当所有作业完成时结束。在这两方面,我都可以给你一些建议。

并行地,您可以使用Array map和Q.all,假设doSomething接受来自jobs的值并返回promise:

return Q.all(jobs.map(doSomething))

要按序列顺序执行作业,请使用Array reduce。

return jobs.reduce(function (previous, job) {
return previous.then(function () {
return doSomething(job);
});
}, Q());

如果要串行执行作业,但仅根据第一个作业的结果继续执行下一个作业,则可以使用reduceRight来组成函数。

return jobs.reduceRight(function (next, job) {
return function (previous) {
return doSomething(job).then(function (result) {
if (result.isGood(previous)) return result;
return next(result);
});
});
}, function fallthrough(previous) {
throw new Error("No result was satisfactory");
})();

如果您有一个数组,其中包含需要按顺序执行的函数,将上一个函数的输出输入下一个函数,则可以更简洁地使用reduce

return functions.reduce(Q.when, Q());

Q的自述中的教程涵盖了更多的案例,我被告知这很有帮助https://github.com/kriskowal/q#tutorial

当您将promise推送到数组时,它看起来就像是在执行您在迭代过程中立即创建的promise。尝试更改。。。

promises.push(promise());

收件人。。。

promises.push(promise);

相关内容

  • 没有找到相关文章

最新更新