I discovered javascript promises recently. An advertised benefit is clean nesting by chaining then clauses.
My code works as expected, but nesting grows just as ugly as when I used callbacks. Is there a better way to use chaining of then to remove all this nesting? Note I need task n to complete before anything in task n+1 can start.
The very simple fixed example
'use strict';
function P1() {
return new Promise((resolve) => {
console.log("starting 1")
setTimeout(() => {
console.log("done 1")
resolve();
}, 100)
})
}
function P2() {
return new Promise((resolve) => {
console.log("must start 2 only after 1 is done")
setTimeout(() => {
console.log("done 2")
resolve();
}, 50)
})
}
function P3() {
return new Promise((resolve) => {
console.log("must start 3 only after 3 is done")
setTimeout(() => {
console.log("done 3")
resolve();
}, 10)
})
}
console.log("this works, but if list was long, nesting would be terribly deep");
// start 1, done 1, start 2, done 2, start 3, done 3.
P1().then(() => {
P2().then(() => {
P3()
})
})
Based on the feedback I should have done
P1().then(() => {
return P2()
}).then(() => {
return P3()
}).catch(() => { console.log("yikes something failed" )})
The real code receives an array of stuff to process sequentially. The suggested format above appears suitable only when the sequence of steps is specified as code. Seems like there should some kind of Promise.do_these_sequentialy, rather than my code constructing the promise chain explicitly. As follows:
'use strict';
function driver(single_command) {
console.log("executing " + single_command);
// various amounts of time to complete command
return new Promise((resolve) => {
setTimeout(() => {
console.log("completed " + single_command);
resolve()
}, Math.random()*1000)
})
}
function execute_series_of_commands_sequentialy(commands) {
var P = driver(commands.shift());
if (commands.length > 0) {
return P.then(() => { return execute_series_of_commands_sequentialy(commands) })
} else {
return P
}
}
execute_series_of_commands_sequentialy([1, 2, 3, 4, 5, 6, 7, 8, 9]).then(() => {
console.log("test all done")
})
P1()
.then(() => P2())
.then(() => P3())
You can make your code more flat. Also explicit construction is an antipattern