Ste Crossley
Ste Crossley

Reputation: 68

Why are my promises not processing asynchronously?

I have two functions, one function, asyncTest_returnPromise simply returns a promise, and another function, asyncTest, calls that promise 3 times by calling Promise.all(promises) on an array of promises. Within each promise in the array, I send one value ("Foo") to the console before the asyncTest_returnPromise function is called, and send another value ("Bar") to the console after it is called.

Given my understanding of the Promise.all function, I would have expected each promise within the array to be processed only after the subsequent promise had been fulfilled, meaning that as both console.log statements are within each promise in the array, the result would have been: Foo Bar Foo Bar Foo Bar

Instead, however, the output seems to be: Foo Foo Foo Bar Bar Bar

As all instances of "Foo" have been sent to the console before even the first "Bar", it seems to me these promises must be being processed concurrently.

Here are the two functions:

function asyncTest_returnPromise() {
    return new Promise((resolve, reject) => {
        resolve()
    })
}

function asyncTest() {
    var promises = []
    for (i = 0; i < 3; i++) {
        promises.push(new Promise((resolve, reject) => {
            console.log("Foo")
            asyncTest_returnPromise().then(_ => {
                console.log("Bar")
                resolve();
            })
        }))
    }
    Promise.all(promises)
}

asyncTest();

So I would like to know, have I misunderstood the purpose of Promise.all or how it works? Has some other part of my code caused all "foo" outputs before all the "bar" outputs? Is there something I need to do to have the entirety of each promise complete before moving on to the next one?

Upvotes: 0

Views: 59

Answers (2)

Sebastian Kaczmarek
Sebastian Kaczmarek

Reputation: 8515

It's just how Event Loop works. Let me explain how it's processed in simple words:

  1. First, the loop starts and runs 3 times. Each time it creates a new microtask and puts it in the microtask queue for later handling. The order in which those microtasks have been created is kept.

  2. Now those microtasks are being handled one at a time, synchronously. Each of those microtasks (which are run synchronously as the Loop runs) executes console.log('Foo'); and then creates another microtask (another Promise) which are queued by the .then() call. So this additional microtask is put into the queue (behind those three first microtasks). It happens for every microtask created by the loop (so it's 3 times). This is where you have Foo printed 3 times.

  3. Now that all our microtasks (3) have been processed, the Event Loop keeps going and takes the next microtasks for processing. This time it's a microtask that runs console.log('Bar');. It happens also three times. Here's where you get Bar printed 3 times.

Of course, there's more that happens in the Event Loop but this is essentially what happens with your Promises here.

Upvotes: 0

Quentin
Quentin

Reputation: 943108

They are running asynchronously.

Each time around the loop you:

  1. Log Foo
  2. Create a promise (which resolves immediately)
  3. Use then to queue up a function to run after the promise resolves

Then the loop goes around for the next iteration.

Afterwards, when the asyncTest function is finished , the event loop is free to look at the queued up functions.

Since all the promises are resolved, they each run (and log Bar).

If you want to wait for a promise before going around the loop again, then you should look at the await keyword which would let asyncTest pause (and go to sleep) until a promise resolved.

Upvotes: 1

Related Questions