Skip to content

Commit 4bcb49e

Browse files
committed
process: add deferTick
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. TODO: - [] Fill in concrete examples - [] Add tests - [] Add benchmarks - [] Do we need async hook logic or not? - [] process._exiting? - [] Anything else we are unhappy with in regard to nextTick which we want to fix?
1 parent 94f824a commit 4bcb49e

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

lib/internal/bootstrap/node.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,9 @@ process.emitWarning = emitWarning;
303303
// bootstrap to make sure that any operation done before this are synchronous.
304304
// If any ticks or timers are scheduled before this they are unlikely to work.
305305
{
306-
const { nextTick, runNextTicks } = setupTaskQueue();
306+
const { nextTick, runNextTicks, deferTick } = setupTaskQueue();
307307
process.nextTick = nextTick;
308+
process.deferTick = deferTick;
308309
// Used to emulate a tick manually in the JS land.
309310
// A better name for this function would be `runNextTicks` but
310311
// it has been exposed to the process object so we keep this legacy name

lib/internal/process/task_queues.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ function setHasTickScheduled(value) {
5353
}
5454

5555
const queue = new FixedQueue();
56+
const deferQueue = new FixedQueue();
5657

5758
// Should be in sync with RunNextTicksNative in node_task_queue.cc
5859
function runNextTicks() {
@@ -93,6 +94,9 @@ function processTicksAndRejections() {
9394
emitAfter(asyncId);
9495
}
9596
runMicrotasks();
97+
while ((tock = deferQueue.shift()) !== null) {
98+
tock.callback.apply(null, tock.args);
99+
}
96100
} while (!queue.isEmpty() || processPromiseRejections());
97101
setHasTickScheduled(false);
98102
setHasRejectionToWarn(false);
@@ -133,6 +137,19 @@ function nextTick(callback) {
133137
queue.push(tickObject);
134138
}
135139

140+
function deferTick(callback, ...args) {
141+
validateFunction(callback, 'callback');
142+
143+
if (process._exiting)
144+
return;
145+
146+
if (tickInfo[kHasTickScheduled] === 0) {
147+
tickInfo[kHasTickScheduled] = 1;
148+
}
149+
150+
deferQueue.push({ callback, args });
151+
}
152+
136153
function runMicrotask() {
137154
this.runInAsyncScope(() => {
138155
const callback = this.callback;
@@ -166,6 +183,7 @@ module.exports = {
166183
setTickCallback(processTicksAndRejections);
167184
return {
168185
nextTick,
186+
deferTick,
169187
runNextTicks,
170188
};
171189
},

0 commit comments

Comments
 (0)