Sources

S1 — MDN: JavaScript execution model

URL: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model

  • authority: official-docs
  • supports: 第 1-3 课:调用栈(后进先出)、任务队列/事件循环(先进先出)、运行至完成、任务只有在栈空时才算完成,以及微任务优先级高于任务。
  • key-fact: "Run-to-completion: Each job is processed completely before any other job is processed." "Stack (of execution contexts): this is what's known as a call stack... It's called a stack because it's last-in-first-out." "A job is considered completed when the stack is empty; then, the next job is pulled from the queue." "HTML event loops split jobs into two categories: tasks and microtasks. Microtasks have higher priority and the microtask queue is drained first before the task queue is pulled." "The code that executes after the completion of an asynchronous action is always provided as a callback function (for example, the promise then() handler, the callback function in setTimeout())."

S2 — MDN: Using microtasks in JavaScript with queueMicrotask()

URL: https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide

  • authority: official-docs
  • supports: 第 3 课:微任务在当前函数/任务结束、且栈空之后才运行;promise 使用微任务队列;整个微任务队列会在下一个任务之前清空。
  • key-fact: "A microtask is a short function which is executed after the function or program which created it exits and only if the JavaScript execution stack is empty." "The oldest runnable task in the task queue will be executed during a single iteration of the event loop. After that, microtasks will be executed until the microtask queue is empty." "JavaScript promises... use the microtask queue to run their callbacks." "the event loop will keep calling microtasks until there are none left in the queue, even if more keep getting added."

S3 — MDN: await

URL: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

  • authority: official-docs
  • supports: 第 4 课:await 只暂停自己所在的 async 函数,把控制权交回调用者,安排一个续接微任务,对已解决的 promise 同样会暂停,并且从不阻塞主线程。
  • key-fact: "Using await pauses the execution of its surrounding async function until the promise is settled." "Even when the used promise is already fulfilled, the async function's execution still pauses until the next tick. In the meantime, the caller of the async function resumes execution." "Control exits the function and returns to the caller. When the awaited expression's value is resolved, another microtask that continues the paused code gets scheduled." "the await expression never blocks the main thread and only defers execution of code that actually depends on the result."

S4 — MDN: async function

URL: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

  • authority: official-docs
  • supports: 第 4 课:async 函数同步运行到第一个 await;await 之后的部分被推迟到之后的 tick。
  • key-fact: "an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously." "as soon as there's one await, the function becomes asynchronous, and execution of following statements is deferred to the next tick."

S5 — MDN: Promise.prototype.then()

URL: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

  • authority: official-docs
  • supports: 第 3 课:.then() 的处理函数是被安排的,不会原地运行,即使 promise 已经落定也永远异步执行。
  • key-fact: "The then() method schedules callback functions for the eventual completion of a Promise — either fulfillment or rejection." "The call always happens asynchronously, even when the current promise is already settled." "then() ... immediately returns another Promise object, allowing you to chain calls."

S6 — MDN: setTimeout()

URL: https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout

  • authority: official-docs
  • supports: 第 1-2 课:setTimeout(fn, 0) 不会立即运行,它被安排到事件循环靠后的一轮,真实延迟可能比要求的更长。
  • key-fact: "setting delay to 0 will execute in the next event cycle rather than "immediately"." "The actual delay may be longer than set."

S7 — HTML Living Standard: Event loops

URL: https://html.spec.whatwg.org/multipage/webappapis.html#event-loops

  • authority: official-docs
  • supports: 第 2-3 课:正式模型:事件循环拥有任务队列和一个独立的微任务队列,而微任务队列不是任务队列。
  • key-fact: "An event loop has one or more task queues." "Each event loop has a microtask queue, which is a queue of microtasks." "The microtask queue is not a task queue."

S8 — Jake Archibald: Tasks, microtasks, queues and schedules

URL: https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

  • authority: authoritative-guide
  • supports: 第 3、5 课:交叉印证微任务在当前执行的脚本/回调之后、下一个任务之前运行,以及 .then() 先于 setTimeout(fn, 0) 打印的经典完整示例。
  • key-fact: "Microtasks are usually scheduled for things that should happen straight after the currently executing script, such as reacting to a batch of actions... The microtask queue is processed after callbacks as long as no other JavaScript is mid-execution, and at the end of each task." promise 回调作为微任务排队,因此会先于排队的(宏)任务(例如定时器)运行。