papillon
papillon

Reputation: 2062

Why is finally executed before Promise's then?

When I execute the following code, the block of code A gets executed before the block of code B.

return new Promise((resolve, reject) => {
  try {
    resolve()
  } finally {
    // block of code A
  }
}).then(() => {
  // block of code B
})

But I don't understand why A is executed first.

The resolution (or rejection) of a promise triggers the then corresponding to it, so I would expect block of code B to be run before block of code A.

From the doc:

When either of these options (resolve/reject) happens, the associated handlers queued up by a promise's then method are called.

I also read this:

the executor is called before the Promise constructor even returns the created object

the executor = the function passed as param to the Promise object.

The latter quote makes me think that the try catch can be finished before the resolution or rejection handlers are triggered (before the executor function is returned from the Promise). It would explain that the finally is triggered before the Promise's then.

HOWEVER, I tried making a call to an external API with fetch and awaiting for the response before continuing, hoping that the Promise function would widely have the time to return the executor function before the try catch is finished:

return new Promise(async (resolve, reject) => {
  try {
    await fetch('https://swapi.co/api/people/1/')
    resolve()
  } finally {
    // block of code A
  }
}).then(() => {
  // block of code B
})

And it turned out that A was still executed before B. I expected the resolution handler to be triggered before A is executed, since resolve is called before A is executed. But I am wrong, and I don't understand why.

May someone explain me please?

Upvotes: 2

Views: 6912

Answers (2)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276386

The promise constructor is always executed synchronously. This means any code inside it will execute right away.

A then block queues a function to execute after the promise is resolved. The function you passed to then runs after all synchronous code.

console.log(1);
Promise.resolve().then(() => console.log(3));
console.log(2); // logs 1, 2, 3

The spec calls this EnqueueJob. Note that you should avoid explicit construction when creating promise returning function. An async function already returns a promise automatically.

Upvotes: 2

Sonal Borkar
Sonal Borkar

Reputation: 561

The finally{} block is part of the try catch block. So, if you have more than one set of try catch block, then each set can have their own finally block, which will get executed when either the try block is finished or the corresponding catch block is finished.

Upvotes: 0

Related Questions