Home > Mobile >  Complex serial and parallel promises resolution
Complex serial and parallel promises resolution

Time:02-16

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 and sequence2) 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),
    ]);
}
  • Related