Search code examples
es6-promise

How to understand the introduction of Promise.resolve in the reduce method of Array


const tasks = [f1, f2, f3];
        tasks.reduce(async (promise, task) => {
            await promise;
            await task();
        }, Promise.resolve)
  • 1、The role of Promise.resolve
  • 2、The role of await promise; Thanks~~

Solution

  • This design pattern using .reduce() is to serialize a number of promise-returning operations. As such, the logic is that you wait on the previous promise, then when it's done you execute your next task and return a promise as value for the next cycle through the loop where the process can be repeated.

    To make that first iteration work without special code for the first iteration, you need a promise that you can initially wait for. So, you pass an already resolved promise created with Promise.resolve() to "prime the pump" and give it an initial promise to use.

    If you unwrap the .reduce() loop, in your example, you essentially end up with this:

    Promise.resolve().then(f1).then(f2).then(f3)
    

    Starting the chain with Promise.resolve() avoids special casing the first iteration of the loop.

    That could be written as:

    f1().then(f2).then(f3)
    

    But, that special cases the first task which really complicates using something like .reduce() which is simplest when you do the same thing with every iteration of the loop. So, starting things off with Promise.resolve() allows the first iteration to do exactly the same thing as all the other iterations.

    As for your two bullet points:

    The role of Promise.resolve()

    To give .reduce() an initial promise for the first iteration to wait for.

    The role of await promise

    That waits until the task from the previous iteration of the loop is done before calling the next task.


    Note: To fully understand this code, you have to fully understand how .reduce() works. You pass it two arguments, your callback function and an initial value. That initial value is passed to the first iteration of the callback as the first argument to the callback (what you named promise).

    Then, whatever value you return from that callback will be passed as the value to the next iteration of the callback. Since you're using an async callback which ALWAYS returns a promise, your callback will always return a promise which is what will get passed to the next iteration of the callback. And, because the first thing your callback does is await promise, you end up "chaining" promises which serializes the execution of your tasks.