So I have this function that does 4 things, which have to be sequenced the following way:
- promise1
- promiseAfter1
// In parallel
- promise2
- promiseAfter2
To get the serial promises I shall write:
async sequence1() {
const result = await promise1();
const finalResult = await promiseAfter1(result);
}
async sequence2() {
const result = await promise2();
const finalResult = await promiseAfter2(result);
}
And then:
async finalSequence() {
await Promise.all([sequence1, sequence2]);
}
But in order to achieve this, I had to create two sub-functions (sequence1
and sequence2
) which I'd like to avoid for code readability among other reasons.
Is there a way to achieve the same result without having to create two sub-functions?
Shouldn't there be something like Promise.sequence
that would sequentially resolve promises?
This would write:
Promise.all([
Promise.sequence([promise1, promiseAfter1]),
Promise.sequence([promise2, promiseAfter2]),
])
Cheers
CodePudding user response:
But in order to achieve this, I had to create two sub-functions (
sequence1
andsequence2
) which I'd like to avoid for code readability among other reasons.
I'd say it's more readable with those functions, rather than less, provided you give them meaningful names. But it's a matter of opinion.
Shouldn't there be something like
Promise.sequence
that would sequentially resolve promises?
Not really, no; it doesn't fit with the other promise combinators (Promise.all
, etc.). The thing about the promise combinators is that they work with promises, but your Promise.sequence
would need to work with functions instead. Remember that Promise.all
, etc., don't make anything happen that wouldn't already have happened, they just observe and combine the results of things completing. That's what promises are for: Observing the results of asynchronous processes.
There is something built-in for doing things in sequence, though, something that takes functions: then
async finalSequence() {
await Promise.all([
promise1().then(promiseAfter1),
promise2().then(promiseAfter2),
]);
}
Or if you don't want to pass the results from one to the next, you could use inline functions:
// Either
async finalSequence() {
await Promise.all([
promise1().then(() => promiseAfter1()),
promise2().then(() => promiseAfter2()),
]);
}
// Or
async finalSequence() {
await Promise.all([
(async () => { await promise1(); await promiseAfter1(); })(),
(async () => { await promise2(); await promiseAfter2(); })(),
]);
}
(Those differ slightly in terms of what ends up in the array from Promise.all
, but you're not using that array, so...)
But if you wanted to write sequence
(say, assuming the functions should be called without arguments) to put in your standard utility library (we all have one, right? :-) ), it's straightforward to do:
async function sequence(functions) {
for (const fn of functions) {
await fn();
}
}
Then as you say, finalSequence
would be:
async finalSequence() {
await Promise.all([
sequence(promise1, promiseAfter1),
sequence(promise2, promiseAfter2),
]);
}