我正在尝试找出处理嵌套的作业树的最快方法,这些作业会在javascript中返回promise。我具有以下条件:
我已经模拟了一个示例,该示例将一堆数字求和,并调用一个公共Web服务来模拟实际工作(不幸的是,由于无法通过https使用公共Web服务,因此我无法对此进行编码):
function sumNumbers(numbersToSum) {
return numbersToSum.reduce((p, current) => {
return p.then(runningTotal => {
return fetch(`http://numbersapi.com/${current.number}/`)
.then(result => {
var parentTotal = runningTotal + current.number;
if (current.children && current.children.length > 0) {
return sumNumbers(current.children)
.then(childrenTotal => {
return childrenTotal + parentTotal;
});
}
else {
return parentTotal;
}
});
});
}, Promise.resolve(0));
}
var numbers = [
{
number: 2,
children: [
{ number: 1 },
{
number: 3,
children: [
{ number: 2 },
{
number: 1,
children: [
{ number: 1 },
{ number: 2 }
]
}
]
},
{ number: 2 }
]
},
{ number: 4 },
{ number: 5 },
{
number: 3,
children: [
{
number: 1,
children: [
{ number: 1 }
]
},
{ number: 2 }
]
}
];
(() => {
var startTime = new Date();
sumNumbers(numbers)
.then(total => {
var finishTime = new Date();
console.log(`${total} (took ${((finishTime - startTime) / 1000)}s)`);
});
})();
当我在Web控制台中运行该命令时,会得到以下结果:
30 (took 2.839s)
此方法有效,但是当作业中有孩子要处理时,父级会等待子级作业完成,然后再解决并继续下一个同级作业。我想知道并行处理子作业是否会更快?
是这种情况吗?如果是这样,您将如何重写示例以利用该方法?如果没有,那么通常有更快的方法吗?
答案 0 :(得分:2)
启动子项工作后立即解决父项问题,然后再将结果求和会更快吗?
是的,会的。如果理解正确,您将只希望顺序处理同级节点,并让每个节点在开始其子节点的工作之前等待其前任节点,而没有一个节点在等待其子节点完成。
或更明确地说,从第一级进行的第一次读取与从第二,第三和第四级进行的第一次读取同时执行。这是4个并行执行而不是串行执行的请求(如op中的示例代码所示),当扩展到更大的示例时,肯定会节省大量时间。
是的,这会更快,但不会显着-最多是一个常数。您仍然必须顺序处理树上的所有叶子。
尽管这样的代码很简单-您只需将fetch(node).then(processChildren)
替换为并发版本:
return Promise.all([
fetch(`http://numbersapi.com/${current.number}/`),
current.children && current.children.length > 0
? sumNumbers(current.children)
: 0
}).then(([result, childrenTotal]) => {
// ^^^^^^
var parentTotal = runningTotal + current.number;
return childrenTotal + parentTotal;
});
我注意到您从未真正使用过result
,所以我想知道为什么您根本不获取任何东西:-)