There are methods such as Q.reduce
and Q.all
that help flattening a promise chain on the specific case of heterogeneous collections of promises. Mind, though, the generic case:
const F = (x) => x;
const a = F(1);
const b = F(2);
const c = F(a + b);
const d = F(a + c);
const e = F(b + c);
console.log(e);
That is, a sequence of assignments on which each term depends on arbitrary previously defined terms. Suppose that F
is an asynchronous call:
const F = (x) => Q.delay(1000).return(x);
I can think in no way to express that pattern without generating an indentation pyramid:
F(100).then(a =>
F(200).then(b =>
F(a+b).then(c =>
F(a+c).then(d =>
F(b+c).then(e =>
F(d+e).then(f =>
console.log(f)
)
)
)
)
)
);
Note that using returned values wouldn't work:
F(100).then(a => F(200))
.then(b => F(a+b))
.then(c => F(a+c))
.then(d => F(b+c))
.then(e => F(d+e))
.then(f => console.log(f));
Since, for example, a
wouldn't be in scope on the second line. What is the proper way to deal with this situation?
Because of the way that subsequent operations rely on multiple bits of previous operations, your choices are:
Do what you've done
Put the variables outside the chain and assign them as you go
Have the entire thing passing around an object with a
, b
, and such on it as properties
#1 is what I'd stick with, barring a really good reason to do either of the other two. Fortunately, that kind of accumulation rarely goes as deep as shown in your question.
async
/await
is the way to do it here some years later (and may have been when the question was posted, the proposal was finished and they could be used with a transpiler), see Sterling's answer for how they could simplify it. Here's a working example:
const F = x => {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 100);
});
};
(async () => {
const a = await F(100);
const b = await F(200);
const c = await F(a+b);
const d = await F(a+c);
const e = await F(b+c);
const f = await F(d+e);
console.log(f);
})()
.catch(error => {
// ...handle/report error...
});
Live on Babel's REPL for those with outdated environments.