Sources

S1 — MDN: JavaScript execution model

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

  • authority: official-docs
  • supports: Lessons 01-03 — the call stack (last-in-first-out), the job queue / event loop (first-in-first-out), run-to-completion, that a job is done only when the stack is empty, and that microtasks have higher priority than tasks.
  • 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: Lesson 03 — a microtask runs after the current function/task and only when the stack is empty; promises use the microtask queue; the whole microtask queue is drained before the next task.
  • 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: Lesson 04 — await pauses only its own async function, returns control to the caller, schedules a continuation microtask, pauses even for an already-resolved promise, and never blocks the main thread.
  • 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: Lesson 04 — an async function runs synchronously up to its first await; after an await the rest is deferred to a later 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: Lesson 03 — a .then() handler is scheduled, not run inline, and always runs asynchronously even when the promise is already settled.
  • 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: Lessons 01-02 — a setTimeout(fn, 0) does not run immediately; it is scheduled to run in a later pass of the event loop, and the real delay can be longer than requested.
  • 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: Lessons 02-03 — the formal model: an event loop has task queues and a separate microtask queue, and the microtask queue is not a task queue.
  • 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: Lessons 03, 05 — cross-corroboration that microtasks run after the currently executing script/callback and before the next task, and the classic worked example of .then() printing before a 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 callbacks are queued as microtasks and therefore run before a queued (macro)task such as a timer.