0

I have a question regarding JavaScript promises and the execution order of the then() method when used with setTimeout. Below is the code in question:

new Promise((resolve) => setTimeout(resolve, 10000, "Resolved!")).then(console.log);

My concern is whether the then() method will be executed before the timer completes. I initially thought that the then() would be executed before the timer due to how JavaScript engines work. Here is my understanding of the process:

  1. The promise is created, and an executor function is passed to it.
  2. The executor function executes synchronously.
  3. The promise executor function sets up a setTimeout, which is handled by other parts of the browser environment and not the JS engine itself.
  4. Once the timer expires, the callback passed to setTimeout will be pushed to the macro-task queue.
  5. However, since the setTimeout takes a long time to finish, the JS engine moves to the then block.
  6. The then() method is executed, and a callback is pushed to the microtask queue.
  7. With an empty call stack, the JS engine first checks for any microtasks in the queue.
  8. It encounters the function from then() and executes it.
  9. At some point in the future, the setTimeout finishes executing and pushes the callback to the macro-task queue.
  10. The JS engine then sees the callback and executes it, which resolves the promise.

But when I run the code, it appears that my understanding is incorrect. Could someone please help me understand this topic better? Your assistance is greatly appreciated. Thank you! Here is the Stack Overflow answers that I have found which clearified some of my doubts: https://stackoverflow.com/questions/66934373/how-then-method-actually-works-in-javascript#:~:text=then()%20method%20will%20insert,get%20the%20result%20Hello%20Stackoverflow%20!

Toby Harnish
  • 90
  • 1
  • 9
  • the `then` function won’t execute until the promise resolves (after the timeout expires and resolve() is called in your example). Consider that the function passed to `then` receives the resolved value of the promise as an argument, so it has to wait for it to resolve. – ray Jul 26 '23 at 01:40
  • Execution will continue below the line in your example while the timeout is offloaded to the environment. – ray Jul 26 '23 at 01:46
  • You seem to be confusing "calling `.then()`" with "calling the callback passed to `.then()`". – Siguza Jul 26 '23 at 01:49
  • Yeah, I think so. So how does it actually work exactly? – Toby Harnish Jul 26 '23 at 01:50
  • `then()` is executed synchronously, the callback passed to it is not queued as microtask directly though. It's only stored at that time. The microtask that will execute it will only be queued when the Promise resolves, and that is after the timeout callback is executed. `then()` could be seen as queuing a microtask only when it's called on a Promise that is *already* resolved. It's not the case here. – Kaiido Jul 26 '23 at 02:20
  • @Kaiido, What about Promise.resolve("Hi"); Will that queue a microtask? – Toby Harnish Aug 20 '23 at 00:36
  • @TobyHarnish no, no microtask is queued untile the Promise's (internal) `then` is called. But if you had `Promise.resolve().then(callback)` then, yes, that would queue a microtask to execute `callback`, that's how we polyfill `queuMicrotask()` – Kaiido Aug 20 '23 at 01:52
  • @Kaiido, Can you explain the internal then that you referenced in your comment? I thought that the `then` method is already being exposed on the promise object - how can it be internal? Thanks for your help and time – Toby Harnish Aug 20 '23 at 16:51
  • You also said that the 'then' will only queue a microtask until the promise resolves. So if Promise.resolve("Hi") resolves the promise immidiately, wouldn't that also queue a microtask? – Toby Harnish Aug 20 '23 at 16:55
  • The .then method will call the internal then, but so will .catch and .finally, hence why Ibtalked about the "internal" one. And yes, `then` will only queue a microtask when its Promise is resolved, but resolving the Promise without calling its `then` doesn't need to queue a microtask, what would that microtask do in your mind? – Kaiido Aug 20 '23 at 21:06
  • @Kaiido, I thought that the job of the then method is only to save the callback if the promise is not resolved yet--and returns another instance of the promise object for chaining purpose. I didn't know that it can enqueue a microtask? Also, can you provide me with a reference where it mentions an internal "then"? Thank you – Toby Harnish Aug 20 '23 at 23:36
  • What would be the use of only returning a new promise if you never can do anything else with these? The *main* purpose of `.then` is indeed to save the callback so that this callback be executed, and it will get executed in a microtask, and that microtask has to be queued. If the promise is already resolved, the callback still has to be called, and it will still be in a microtask. The ["internal then"](https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-performpromisethen) – Kaiido Aug 21 '23 at 00:04
  • Are you stating that the microtask is the callback itself, or the callback is being invoked within a microtask function? – Toby Harnish Aug 21 '23 at 01:08
  • The callback is being invoked in a microtask. Microtasks aren't functions though. – Kaiido Aug 21 '23 at 04:49

0 Answers0