Skip to content

doc: clarify cjs and esm scheduling difference between queueMicrotask() and process.nextTick() #56659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions doc/api/process.md
Original file line number Diff line number Diff line change
Expand Up @@ -3020,34 +3020,40 @@ function definitelyAsync(arg, cb) {

### When to use `queueMicrotask()` vs. `process.nextTick()`

The [`queueMicrotask()`][] API is an alternative to `process.nextTick()` that
also defers execution of a function using the same microtask queue used to
execute the then, catch, and finally handlers of resolved promises. Within
Node.js, every time the "next tick queue" is drained, the microtask queue
The [`queueMicrotask()`][] API is an alternative to `process.nextTick()` that instead of using the
"next tick queue" defers execution of a function using the same microtask queue used to execute the
then, catch, and finally handlers of resolved promises.

Within Node.js, every time the "next tick queue" is drained, the microtask queue
is drained immediately after.

So in CJS modules `process.nextTick()` callbacks are always run before `queueMicrotask()` ones.
However since ESM modules are processed already as part of the microtask queue, there
`queueMicrotask()` callbacks are always exectued before `process.nextTick()` ones since Node.js
is already in the process of draining the microtask queue.

```mjs
import { nextTick } from 'node:process';

Promise.resolve().then(() => console.log(2));
queueMicrotask(() => console.log(3));
nextTick(() => console.log(1));
Promise.resolve().then(() => console.log('resolve'));
queueMicrotask(() => console.log('microtask'));
nextTick(() => console.log('nextTick'));
// Output:
// 1
// 2
// 3
// resolve
// microtask
// nextTick
```

```cjs
const { nextTick } = require('node:process');

Promise.resolve().then(() => console.log(2));
queueMicrotask(() => console.log(3));
nextTick(() => console.log(1));
Promise.resolve().then(() => console.log('resolve'));
queueMicrotask(() => console.log('microtask'));
nextTick(() => console.log('nextTick'));
// Output:
// 1
// 2
// 3
// nextTick
// resolve
// microtask
```

For _most_ userland use cases, the `queueMicrotask()` API provides a portable
Expand Down
Loading