# Microtasks Promise handlers `.then`/`.catch`/`.finally` are always asynchronous. Even when a Promise is immediately resolved, the code on the lines *below* `.then`/`.catch`/`.finally` will still execute before these handlers . Here's the demo: ```js run let promise = Promise.resolve(); promise.then(() => alert("promise done!")); alert("code finished"); // this alert shows first ``` If you run it, you see `code finished` first, and then `promise done!`. That's strange, because the promise is definitely done from the beginning. Why did the `.then` trigger afterwards? What's going on? ## Microtasks queue Asynchronous tasks need proper management. For that, the standard specifies an internal queue `PromiseJobs`, more often referred to as "microtask queue" (v8 term). As said in the [specification](https://tc39.github.io/ecma262/#sec-jobs-and-job-queues): - The queue is first-in-first-out: tasks enqueued first are run first. - Execution of a task is initiated only when nothing else is running. Or, to say that simply, when a promise is ready, its `.then/catch/finally` handlers are put into the queue. They are not executed yet. JavaScript engine takes a task from the queue and executes it, when it becomes free from the current code. That's why "code finished" in the example above shows first. ![](promiseQueue.svg) Promise handlers always go through that internal queue. If there's a chain with multiple `.then/catch/finally`, then every one of them is executed asynchronously. That is, it first gets queued, and executed when the current code is complete and previously queued handlers are finished. **What if the order matters for us? How can we make `code finished` work after `promise done`?** Easy, just put it into the queue with `.then`: ```js run Promise.resolve() .then(() => alert("promise done!")) .then(() => alert("code finished")); ``` Now the order is as intended. ## Unhandled rejection Remember `unhandledrejection` event from the chapter ? Now we can see exactly how JavaScript finds out that there was an unhandled rejection **"Unhandled rejection" occurs when a promise error is not handled at the end of the microtask queue.** Normally, if we expect an error, we add `.catch` to the promise chain to handle it: ```js run let promise = Promise.reject(new Error("Promise Failed!")); *!* promise.catch(err => alert('caught')); */!* // doesn't run: error handled window.addEventListener('unhandledrejection', event => alert(event.reason)); ``` ...But if we forget to add `.catch`, then, after the microtask queue is empty, the engine triggers the event: ```js run let promise = Promise.reject(new Error("Promise Failed!")); // Promise Failed! window.addEventListener('unhandledrejection', event => alert(event.reason)); ``` What if we handle the error later? Like this: ```js run let promise = Promise.reject(new Error("Promise Failed!")); *!* setTimeout(() => promise.catch(err => alert('caught')), 1000); */!* // Error: Promise Failed! window.addEventListener('unhandledrejection', event => alert(event.reason)); ``` Now, if you run it, we'll see `Promise Failed!` message first, and then `caught`. If we didn't know about microtasks queue, we could wonder: "Why did `unhandledrejection` handler run? We did catch the error!". But now we understand that `unhandledrejection` is generated when the microtask queue is complete: the engine examines promises and, if any of them is in "rejected" state, then the event triggers. In the example above, `.catch` added by `setTimeout` also triggers, but later, after `unhandledrejection` has already occurred, so that doesn't change anything. ## Summary Promise handling is always asynchronous, as all promise actions pass through the internal "promise jobs" queue, also called "microtask queue" (v8 term). So, `.then/catch/finally` handlers are always called after the current code is finished. If we need to guarantee that a piece of code is executed after `.then/catch/finally`, we can add it into a chained `.then` call. In most Javascript engines, including browsers and Node.js, the concept of microtasks is closely tied with "event loop" and "macrotasks". As these have no direct relation to promises, they are covered in another part of the tutorial, in the chapter .