Skip to content

Commit

Permalink
process: add deferTick
Browse files Browse the repository at this point in the history
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?
  • Loading branch information
ronag committed Jan 15, 2024
1 parent 94f824a commit 4bcb49e
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,9 @@ process.emitWarning = emitWarning;
// bootstrap to make sure that any operation done before this are synchronous.
// If any ticks or timers are scheduled before this they are unlikely to work.
{
const { nextTick, runNextTicks } = setupTaskQueue();
const { nextTick, runNextTicks, deferTick } = setupTaskQueue();
process.nextTick = nextTick;
process.deferTick = deferTick;
// Used to emulate a tick manually in the JS land.
// A better name for this function would be `runNextTicks` but
// it has been exposed to the process object so we keep this legacy name
Expand Down
18 changes: 18 additions & 0 deletions lib/internal/process/task_queues.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function setHasTickScheduled(value) {
}

const queue = new FixedQueue();
const deferQueue = new FixedQueue();

// Should be in sync with RunNextTicksNative in node_task_queue.cc
function runNextTicks() {
Expand Down Expand Up @@ -93,6 +94,9 @@ function processTicksAndRejections() {
emitAfter(asyncId);
}
runMicrotasks();
while ((tock = deferQueue.shift()) !== null) {
tock.callback.apply(null, tock.args);
}
} while (!queue.isEmpty() || processPromiseRejections());
setHasTickScheduled(false);
setHasRejectionToWarn(false);
Expand Down Expand Up @@ -133,6 +137,19 @@ function nextTick(callback) {
queue.push(tickObject);
}

function deferTick(callback, ...args) {
validateFunction(callback, 'callback');

if (process._exiting)
return;

if (tickInfo[kHasTickScheduled] === 0) {
tickInfo[kHasTickScheduled] = 1;
}

deferQueue.push({ callback, args });
}

function runMicrotask() {
this.runInAsyncScope(() => {
const callback = this.callback;
Expand Down Expand Up @@ -166,6 +183,7 @@ module.exports = {
setTickCallback(processTicksAndRejections);
return {
nextTick,
deferTick,
runNextTicks,
};
},
Expand Down

0 comments on commit 4bcb49e

Please sign in to comment.