DEV Community

Cover image for The Power Of reduce() - Sequentially Queue Promises
Daniel Bellmas
Daniel Bellmas

Posted on • Edited on

The Power Of reduce() - Sequentially Queue Promises

Yes reduce, the almighty, feared among the mortals...

But in all seriousness, a lot of new and experienced developers alike, avoid trying to understand this one, and with no good reason if you ask me.

If you don't yet understand it, I recommend this site, it has some great examples that will definitely get you started.


Now that we've got that behind us, Let's talk about the true power of reduce πŸ”₯⚑️πŸ”₯⚑️πŸ”₯

array.reduce( async (previousPromise, item) => {
  await previousPromise;

  return methodThatReturnsAPromise(item);
}, Promise.resolve());
Enter fullscreen mode Exit fullscreen mode

Let's break it down:

  1. First we initialize the accumulator with Promise.resolve() which returns a Promise that is resolved with the given value (the argument in passed), in our case - undefined but we don't care about that 'cause we only want the power of the Promise.

  2. We start the loop by awaiting for the accumulator (bear with me it will make sense after the first iteration) and after that we are returning another promise!

  3. Now, the accumulator is equal to methodThatReturnsAPromise with the first element of the array as its argument.

  4. And now the cycle continues...we await the accumulator and then make it equal to the next promise.

Every promise will happen one after the other.
The next promise will wait for the previous promise to finish before it executes.

A promise can be fetch API call that we want to do one by one to not overload the system.

That's it, we've harnessed the true power of reduce!
We are now able to sequentially queue promises πŸ”₯

For a more detailed explanation visit css-tricks


Bonus: reduceRight()

It works the same way as reduce(). However, It works in the opposite direction.

reduce() starts at the first element and travels towards the last. Oppositely, reduceRight() starts at the last element and goes to the first element.

The only use case I saw for that one so far if for avoiding too many context providers from spamming your React App.js
(Indentation Hell)

<BrowserRouter>
    <AuthProvider>
        <ThemeProvider>
            <ChatProvider>
                <App />
            </ChatProvider>
        </ThemeProvider>
    </AuthProvider>
</BrowserRouter>
Enter fullscreen mode Exit fullscreen mode

Indentation Hell

The way to solve it (in a cool way with reduce) while still keeping the same order is with reduceRight().

export default function Compose(props: Props) {
    const { components = [], children } = props

    return (
        <>
            {components.reduceRight((acc, Comp) => {
                return <Comp>{acc}</Comp>
            }, children)}
        </>
    )
}
Enter fullscreen mode Exit fullscreen mode

And in the you can use is like so:

<Compose components={[BrowserRouter, AuthProvider, ThemeProvider, ChatProvider]}>
    <App />
</Compose>
Enter fullscreen mode Exit fullscreen mode

This is the stackoverflow question that first introduced it to me.

As always, thank you for reading! πŸ™πŸΌπŸ¦Ύ

Top comments (0)