From ebca456c1293d0d7eadc6bc64fd0e7f4937392a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E7=8E=A5?= Date: Sat, 8 Jun 2019 22:31:33 +0800 Subject: [PATCH 1/8] 07-microtask-queue / article.md microtasks-and-event-loop --- 6-async/07-microtask-queue/article.md | 191 ++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 6-async/07-microtask-queue/article.md diff --git a/6-async/07-microtask-queue/article.md b/6-async/07-microtask-queue/article.md new file mode 100644 index 0000000000..820aa31294 --- /dev/null +++ b/6-async/07-microtask-queue/article.md @@ -0,0 +1,191 @@ + +# Microtasks and event loop + +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 + +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.png) + +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. + +## Event loop + +In-browser JavaScript execution flow, as well as Node.js, is based on an *event loop*. + +"Event loop" is a process when the engine sleeps and waits for events. When they occur - handles them and sleeps again. + +Events may come either comes from external sources, like user actions, or just as the end signal of an internal task. + +Examples of events: +- `mousemove`, a user moved their mouse. +- `setTimeout` handler is to be called. +- an external `