Deep Dive into async/await, Promise, and Event Loop Mechanics in JavaScript
This article explains how async functions, await expressions, and Promise objects interact with JavaScript's event loop, illustrating the differences in micro‑task scheduling through numerous code examples and detailing how return values affect the number of queued tasks.
This article provides a thorough analysis of JavaScript's asynchronous mechanisms, focusing on how async functions, await expressions, and Promise objects cooperate with the event loop and micro‑task queue.
It begins by showing a simple example where an async function awaits a newly created promise, followed by a series of .then calls. The expected console output demonstrates that the promise constructor runs synchronously, while the .then callbacks are queued as micro‑tasks:
async function async1() {
await new Promise((resolve, reject) => { resolve(); })
console.log('A');
}
async1();
new Promise((resolve) => { console.log('B'); resolve(); })
.then(() => console.log('C'))
.then(() => console.log('D'));
// Output: B A C DThe article then explores how the return value of an async function determines how many micro‑tasks are created. Three cases are presented:
Returning a non‑thenable value (e.g., a number) creates no additional micro‑tasks.
Returning a thenable object creates one extra micro‑task.
Returning a real Promise creates two extra micro‑tasks.
Each case is illustrated with concise code snippets and the resulting console order, reinforcing the rule that the JavaScript engine treats the return type specially.
Further sections compare the behavior of await when its operand is a plain value, a non‑thenable function, a thenable object, or a genuine promise. Key observations include:
Awaiting a non‑thenable value adds a single micro‑task but does not wait for it.
Awaiting a thenable forces the engine to wait for one then call.
Awaiting a promise (in modern engines) adds only one micro‑task, whereas older versions added two.
Practical interview‑style examples demonstrate how mixing synchronous code, setTimeout (macro‑tasks), and various async patterns affect the final output order. The step‑by‑step breakdown clarifies why certain logs appear earlier or later.
Finally, the article summarizes the core conclusions: the number of micro‑tasks triggered by an async function depends on the type of its return value, and await only proceeds once the right‑hand expression yields a concrete result.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.