-
Notifications
You must be signed in to change notification settings - Fork 28.9k
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
Inconsistent behavior of nextTick and queueMicrotask #51156
Comments
@jasnell what do you think? |
Just to expand a bit. There is an assumption that |
I'm adding this to the TSC agenda for visibility and help with triaging the severity of the issue. |
Would probably be a good idea to update https://nodejs.org/en/guides/event-loop-timers-and-nexttick to also include promises and microticks. |
It's not entirely clear to me what is the expected output in the OP, did you mean to say that you expect a |
The expectation is that:
and
Should have the same output, which they don't. |
You mean neither of them should log anything or they should both log or either is fine as long as they are the same? I am guessing from the OP (in the context of error handling) that you want both to log? |
I think you could argue that either behavior is correct (or at least not incorrect). The problem here is that they are not consistent. |
Hello @ronag, I would like to continue working on this issue, however, as mentioned on your PR, I guess a simple search and replace won't work? |
@NiharPhansalkar I don't think this is a good starter issue. Not even us in the technical steering are sure what to do about this issue. |
@benjamingr here is the patch that fixes the behavior... but it breaks a lot of tests: diff --git a/lib/internal/process/task_queues.js b/lib/internal/process/task_queues.js
index bcb5eef841..04bdb07122 100644
--- a/lib/internal/process/task_queues.js
+++ b/lib/internal/process/task_queues.js
@@ -67,6 +67,7 @@ function runNextTicks() {
function processTicksAndRejections() {
let tock;
do {
+ runMicrotasks();
while ((tock = queue.shift()) !== null) {
const asyncId = tock[async_id_symbol];
emitBefore(asyncId, tock[trigger_async_id_symbol], tock);
@@ -92,7 +93,6 @@ function processTicksAndRejections() {
emitAfter(asyncId);
}
- runMicrotasks();
} while (!queue.isEmpty() || processPromiseRejections());
setHasTickScheduled(false);
setHasRejectionToWarn(false); |
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 (comment) Refs: nodejs#51070 Refs: nodejs#51156
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 (comment) Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
Unfortunately I don't believe there's a great fix here other than to begin transitioning from |
Even that doesn't fully resolve the issue. We need a primitive that runs after micro tasks. |
Well, it's not even really that. The key issue is the way we communicate errors and other state changes using non-persistent synchronous events that are easily missed. That is actually the thing I'd prefer we start to change here, but obviously that's also quite difficult. This is absolutely one of the ways in which web streams handily beats node.js streams. For instance, we could hypothetically introduce a new function run (name) {
return new Promise((resolve) => {
const e = new EventEmitter()
process.nextTick(() => {
e.emit('error', new Error())
});
resolve(e)
}).then(((e) => {
e.whenErrored.then((err) => /* ... */);
}))
} |
I disagree with your view of the root problem. The problem is that we have two API paradigms here (async callbacks and async events) that are inherently incompatible with the micro task queue. Note that this is a much more generic problem than just the error event. Though I agree it's more prevalent in that context. |
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
This resolve multiple timing issues related to promises and nextTick. As well as resolving zaldo in promise only code, i.e. our current best practice of using process.nextTick will always apply and work. Refs: nodejs#51156 Refs: nodejs#51156 (comment) Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs#51156 PR-URL: nodejs#51267
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Adds a new scheduling primitive to resolve zaldo when mixing traditional Node async programming with async/await and Promises. We cannot "fix" nextTick without breaking the whole ecosystem. nextTick usage should be discouraged and we should try to incrementally move to this new primitive. Refs: nodejs#51156 Refs: nodejs#51280 Refs: nodejs#51114 Refs: nodejs#51070 Refs: nodejs/undici#2497 PR-URL: nodejs#51471
Consider this snippet:
This results in
Why is this an issue? In most part of Node.js core,
we use
process.nextTick(() => ee.emit('error'))
to let users install event handlers.However, if an
EventEmitter
is returned by anasync function
, there is a significant possibility that the error could not be caught.(This is essentially a problem for Node.js streams).
The text was updated successfully, but these errors were encountered: