Short questions: Why is there no Promise.chain in Javascript (comparable to Promise.all)? Is my implementation o.k.?
My 'codec' behaved wrong:
The problem: The order of the database calls for the node creation (Step 2) got mixed up at execution time.
Solution: I had to chain the database calls in correct order before the methods became executed.
/**
* chains a list of functions (that return promises) and executes them in the right order
* [function() {return Promise.resolve();}, function() {return Promise.resolve();}]
*
* @param funcs is an array of functions returning promises
* @returns {Promise}
*/
function chain_promises(funcs) {
if (funcs.length < 1) {
return Promise.resolve();
}
var i = 0;
return chain_executor(funcs, i);
}
/**
* Recursive help method for chain_promises
* 1) executes a function that returns a promise (no params allowed)
* 2) chains itself to the success resolve of the promise
*
* @param funcs is an array of functions returning promises
* @param i is the current working index
*/
function chain_executor(funcs, i) {
var promise = funcs[i]();
return promise.then(function(){
console.log(i);
if (funcs.length > i+1) {
return chain_executor(funcs, i+1);
} else {
return Promise.resolve();
}
})
}
Using Array#reduce you can create this function
const chain_promises = arrayOfFn => arrayOfFn.reduce((promise, fn) =>
promise.then(results =>
fn().then(result =>
results.concat(result)
)
), Promise.resolve([])
);
or if you're into one-liners
const chain_promises = arrayOfFn => arrayOfFn.reduce((promise, fn) => promise.then(results => fn().then(result => results.concat(result))), Promise.resolve([]));
These have the added benefit that the resolved values are all available in the .then
e.g.
const chain_promises = arrayOfFn => arrayOfFn.reduce((promise, fn) =>
promise.then(results =>
fn().then(result =>
results.concat(result)
)
), Promise.resolve([])
);
const wait_promise = (time, result) => new Promise(resolve => setTimeout(resolve, time, result));
var funcs = [
() => wait_promise(300, 'p1').then(value => ({value, date: new Date()})),
() => wait_promise(400, 'p2').then(value => ({value, date: new Date()})),
() => wait_promise(100, 'p3').then(value => ({value, date: new Date()}))
];
const start = new Date();
chain_promises(funcs)
.then(results =>
results.reduce((a, b) => {
console.log(b.value, b.date - a);
return b.date;
}, start)
);
Also, passing an empty array to this function won't break - you'll end up with an empty array as the resolved value