I'm trying to work out the fastest way of processing a nested tree of jobs that return promises in javascript. I have the following conditions:
- The process should return a promise that only resolves when all of the nested jobs are complete.
- Each job at the same level needs to be processed in sequence, but children can be processed in parallel.
- I can't use await/async.
I have mocked up an example that sums a bunch of numbers and calls a public web service to simulate doing actual work (unfortunately I can't codepen this as the public web service is not available over https):
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)`);
});
})();
When I run that in my web console i get the following result:
30 (took 2.839s)
This approach works but when a job has children to process the parent waits for the child jobs to finish before resolving and moving on to the next sibling job. I'm wondering whether it would be faster to process the child jobs in parallel?
Is this the case? If so how would you rewrite the example to take advantage of that approach? If not, is there a faster way of doing this in general?