Skip to content
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

Rule proposal: prefer-queue-microtask #1346

Open
kevinoid opened this issue Jun 8, 2021 · 9 comments
Open

Rule proposal: prefer-queue-microtask #1346

kevinoid opened this issue Jun 8, 2021 · 9 comments

Comments

@kevinoid
Copy link

kevinoid commented Jun 8, 2021

queueMicrotask() serves a similar purpose to process.nextTick() with the additional advantage that queueMicrotask() is specified in the WHATWG HTML Living Standard and supported on both modern browsers and Node.js (v11.0.0 and later).

When to use queueMicrotask() vs. process.nextTick() in the Node.js API documentation states:

For most userland use cases, the queueMicrotask() API provides a portable and reliable mechanism for deferring execution that works across multiple JavaScript platform environments and should be favored over process.nextTick(). In simple scenarios, queueMicrotask() can be a drop-in replacement for process.nextTick().

I propose adding a rule to warn when process.nextTick is used, and suggest queueMicrotask() as an alternative.

Fail

process.nextTick(() => process.exit(0));
process.nextTick(process.exit);
process.nextTick(process.exit, 1);
const fun = process.nextTick;
fun(process.nextTick);

Pass

queueMicrotask(() => process.exit(0));
queueMicrotask(process.exit);
// Note: queueMicrotask takes exactly 1 arg.
// Fail example fixed using .bind().
queueMicrotask(process.exit.bind(undefined, 1));
// Not sure if this should be auto-fixed.
// fun may be called with multiple args.
const fun = queueMicrotask;
// Not sure if this should be auto-fixed.
// fun may call its argument with multiple args.
fun(process.nextTick);
@fisker
Copy link
Collaborator

fisker commented Jun 9, 2021

I never used process.nextTick in Node.js, but in browser, I used setTimeout setImmediate requestAnimationFrame MutationObserver Promise#then to do similar thing.

@kevinoid
Copy link
Author

kevinoid commented Jun 9, 2021

Good points. Lots of APIs with subtle differences. I've also used those at different times, or for different purposes. It's complicated.

@fisker Any reservations about a rule to prefer queueMicrotask() to process.nextTick() specifically? Or are you considering a rule to prefer any of the others? In either case, I'd be happy to discuss the differences and work through the details.

@fisker
Copy link
Collaborator

fisker commented Jun 10, 2021

What I was saying, I think queueMicrotask should be preferred, but check process.nextTick is not going to help me at all.

@sindresorhus
Copy link
Owner

I never used process.nextTick in Node.js, but in browser, I used setTimeout setImmediate requestAnimationFrame MutationObserver Promise#then to do similar thing.

I will try to summarize the differences as far as I know it:

  • setTimeout(..., 0) executes at the end of the event loop run (after all tasks).
  • setImmediate() executes after all I/O tasks.
  • requestAnimationFrame is about rendering.
  • MutationObserver is for DOM mutatations, but has been used as a hack to get the same behavior as queueMicrotask.
  • Promise#then does almost the same as queueMicrotask as it adds the callback to the micro-task queue.

@sindresorhus
Copy link
Owner

We could support Promise#then, but it will conflict with rules enforcing await. And when used with await it solves a different problem:

(async () => {
	// Cannot use `queueMicrotask` here.
	await ''; // Defer a micro-task tick.

	console.log('Hello');
})();

@sindresorhus
Copy link
Owner

setTimeout and setImmediate works differently, so changing to queueMicrotask might cause weird bugs or not be possible at all. We could potentially add an option to make it opt-in.

@sindresorhus
Copy link
Owner

Ideally, we would have a rule prefer-set-immediate which would prefer it over setTimeout(..., 0), but setImmediate doesn't work in the browser, so it's not a good API to use.

@sindresorhus
Copy link
Owner

Seems like we'll eventually get another alternative, so we can put this rule on hold until it's a reality:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants