How does Promise's .then and .catch work under the hood?

Viewed 235

I already know how Promise works but I'm trying to dive deeper more to strengthen my fundamental!

So after reading so many stackoverflow posts, I found out, there's two major array properties in every promise object called onFulfillment and onRejection which are empty array and we use .then to fill the onFulfillment array and .catch or .then's second argument to fill onRejection empty array!

And once our promise is settled, functions from those arrays are put into the microtask queue for later execution.

If our promise was resolved, functions from hidden onFulfillment array will be put onto the task queue but if our promise was rejected, functions from onRejection array will be put onto the task queue for later execution, however, when I tested this theory, that doesn't seem to be the case!

I'm sure my English is not easy to understand so here's some code that will hopefully give you all some sense of what I'm talking about.

let p = new Promise(function (resolve, reject){

  setTimeout(reject, 1000)

})

p.then(x => console.log('done'))
.then(null, x => console.log(true))

p.catch(x => console.log('done'))

We have one .then and one .catch which we put into the onFulfillment and onRejection array respectively and after 1000 ms, what function is put onto the microtask queue depends on if our promise was resolved or rejected. In our case, its being rejected so it only makes sense to put the .catch's function onto the microtask queue however, it seems like even .then's function is being put onto the task queue!

It doesn't literally run but it's evaluated to a rejected promise, but if thats the case, .then's function was put onto the microtask queue and run/evaluted to which means its incorrect that what function is run depends on if our promise was resolved or rejected, it seems like both .then and .catch will run/evaluated.

1 Answers

We use .then to fill the onFulfillment array and .catch or .then's second argument to fill onRejection empty array!

Not exactly. then always puts handlers in both arrays, to be notified when the promise settles. These handlers (which are not the passed arguments!) then

  • either call the respective callback with the result/error value, and resolve the promise which .then() had returned with the call result,
  • or, if no callback for the respective state was passed, directly propagate the value to the promise which .then() had returned

You can do .then(onFulfilled, onRejected), .then(onFulfilled, null), .then(null, onRejected) or .then(null, null) - they all install two handlers.

Related