nextTick use case

239 views
Skip to first unread message

Onteria

unread,
May 30, 2011, 2:36:50 PM5/30/11
to nodejs
I'm somewhat confused on a real world use case for nextTick:

http://nodejs.org/docs/latest/api/process.html#process.nextTick

"On the next loop around the event loop call this callback. This is
not a simple alias to setTimeout(fn, 0), it's much more efficient."

When does this "event loop" come around, and why would I want to call
a function at this point? Since it mentions setTimeout, I'm assuming
this only gets called once.

mscdex

unread,
May 31, 2011, 1:58:39 AM5/31/11
to nodejs
On May 30, 2:36 pm, Onteria <onte...@live.jp> wrote:
> I'm somewhat confused on a real world use case for nextTick:
>
> http://nodejs.org/docs/latest/api/process.html#process.nextTick

nextTick is handy in many situations. It allows you to defer some task
until the next tick of the event loop, giving events and such to occur
quicker depending on how long some of your code blocks.

You could use it to break up a (long) synchronous task that would
ordinarily take a long time to finish, into multiple steps. An example
of this might be if you're receiving data from a tcp socket, where
requests are delimited by some predetermined byte(s). You may receive
a chunk that contains more than one complete request. After breaking
apart the chunk into separate requests, you could either do a while
loop until there are no more requests to process, or you could process
the first one and then process the next one after the next tick, and
so on. This means you block less.

You could also use it to keep the stack from potentially growing very
large. For example, you could have an event that executes a callback
which calls some function that causes another (or even the same) event
to be emitted, which causes more callbacks to be executed, which could
in turn emit more events, etc. So instead you could emit the event(s)
after the next tick to help alleviate this. Some might consider this a
premature optimization as the stack should (hopefully) eventually
unwind at some point, but I'd rather not have to worry about something
like that ever happening in my modules.

Marcel Laverdet

unread,
May 31, 2011, 2:46:42 AM5/31/11
to nod...@googlegroups.com
I do some nextTick trickery where if I do something like:

for (var ii = 0; ii < 10; ++ii) {
  getSomeObject(ii, function(err, val) {
  });
}

It doesn't actually issue a request for that data until nextTick. That way I can batch up requests for external data using a WHERE IN (MySQL) or multiget (memcache) or what have you.


--
You received this message because you are subscribed to the Google Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com.
To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.


Major Flux

unread,
May 31, 2011, 3:01:33 AM5/31/11
to nod...@googlegroups.com
I am always confused about this too.  What exactly does next tick mean? This is what I think it is, which likely could be wrong -

Say there is an event queue with these events (event 1 to 3) sitting in it waiting to be to be popped and be executed.  But at this point in time if there is a nextTick event callback t1 comes in, does it mean that node will execute t1 before e1?

--> [e1][e2][e3]

[t1]

Austin

mscdex

unread,
May 31, 2011, 3:33:21 AM5/31/11
to nodejs
On May 31, 3:01 am, Major Flux <majorfl...@gmail.com> wrote:
> I am always confused about this too.  What exactly does next tick mean? This
> is what I think it is, which likely could be wrong -

From what I understand functions passed to nextTick are executed at
the beginning of the next time around the event loop.

For example, here's your event loop with some events on it:

Beginning-------(event 1)-(event 2)-(event 3)----End
^_________________________________________________|
^--functions passed to nextTick execute here

So inside event 1, say you have some code that executes a callback.
Instead of executing it immediately, you could do
`process.nextTick(callback);` which will return immediately, execute
the rest of your code, and then continue on with any other events (2
and 3) until the current execution reaches the end of the event loop.
When it reaches the end, it loops back to the beginning. At this point
node takes the callback function previously passed to nextTick and
executes it before anything else on the event loop. One trip through
the event loop is one tick.

Marcel Laverdet

unread,
May 31, 2011, 3:30:59 AM5/31/11
to nod...@googlegroups.com
They should go in order. e1, e2, e3, t1. Perhaps nextTick isn't the best name for the function because it just adds your event to the queue.

But if you have order-sensitive nextTick calls you're probably doing something bad. IMO if you're using nextTick for anything other than "wait for this tick to finish, and then do this other thing some time soon after" you're using it wrong.

mscdex

unread,
May 31, 2011, 3:49:21 AM5/31/11
to nodejs
On May 31, 3:30 am, Marcel Laverdet <mar...@laverdet.com> wrote:
> But if you have order-sensitive nextTick calls you're probably doing
> something bad. IMO if you're using nextTick for anything other than "wait
> for this tick to finish, and then do this other thing some time soon after"
> you're using it wrong.

I'm not sure what you mean by this. Functions given to nextTick will
always be executed in order because they are simply pushed onto an
array and executed from beginning to end.

Major Flux

unread,
May 31, 2011, 4:03:21 AM5/31/11
to nod...@googlegroups.com
thanks for explaining that, that actually makes a lot of sense.  But how does that different from doing setTimeout(0, t1) inside e1? behaviorally they seem the same as far as order of execution that t1 is processed after all existing events on the queue.  So I guess nextTick is basically just saving the overhead of having a timer?


--

Marcel Laverdet

unread,
May 31, 2011, 4:12:03 AM5/31/11
to nod...@googlegroups.com
> I'm not sure what you mean by this. Functions given to nextTick will
> always be executed in order because they are simply pushed onto an
> array and executed from beginning to end.

Yeah you /can/ depend on the order but I'm saying if you write software that depends on the order it's bad design in most cases.

// Bad
var foo;
process.nextTick(function() {
  foo = 1;
});
process.nextTick(function() {
  console.log(foo);
});

// Good
process.nextTick(function() {
  var foo = 1;
  process.nextTick(function() {
    console.log(foo);
  });
});

> thanks for explaining that, that actually makes a lot of sense.  But how does
> that different from doing setTimeout(0, t1) inside e1? behaviorally they seem
> the same as far as order of execution that t1 is processed after all existing
> events on the queue.  So I guess nextTick is basically just saving the
> overhead of having a timer?

Yes they are functionally the same, but setTimeout creates a timer, invokes libevent, and a bunch of other stuff. process.nextTick() is done all in Javascript. Also you have your parameters to setTimeout() reversed; the callback is the first param ).


--

Marcel Laverdet

unread,
May 31, 2011, 4:13:56 AM5/31/11
to nod...@googlegroups.com
> I'm not sure what you mean by this. Functions given to nextTick will
> always be executed in order because they are simply pushed onto an
> array and executed from beginning to end.

Yeah you /can/ depend on the order but I'm saying if you write software that depends on the order it's bad design in most cases.

// Bad
var foo;
process.nextTick(function() {
  foo = 1;
});
process.nextTick(function() {
  console.log(foo);
});

// Good
process.nextTick(function() {
  var foo = 1;
  process.nextTick(function() {
    console.log(foo);
  });
});

> thanks for explaining that, that actually makes a lot of sense.  But how does
> that different from doing setTimeout(0, t1) inside e1? behaviorally they seem
> the same as far as order of execution that t1 is processed after all existing
> events on the queue.  So I guess nextTick is basically just saving the
> overhead of having a timer?

Yes they are functionally the same, but setTimeout creates a timer, invokes libevent, and a bunch of other stuff. process.nextTick() is done all in Javascript. Also you have your parameters to setTimeout() reversed; the callback is the first param ).

On Tue, May 31, 2011 at 4:49 PM, mscdex <msc...@gmail.com> wrote:

--

Marcel Laverdet

unread,
May 31, 2011, 4:27:16 AM5/31/11
to nod...@googlegroups.com
> I'm not sure what you mean by this. Functions given to nextTick will
> always be executed in order because they are simply pushed onto an
> array and executed from beginning to end.

Yeah you /can/ depend on the order but I'm saying if you write software that depends on the order it's bad design in most cases.

// Bad
var foo;
process.nextTick(function() {
  foo = 1;
});
process.nextTick(function() {
  console.log(foo);
});

// Good
process.nextTick(function() {
  var foo = 1;
  process.nextTick(function() {
    console.log(foo);
  });
});

> thanks for explaining that, that actually makes a lot of sense.  But how does
> that different from doing setTimeout(0, t1) inside e1? behaviorally they seem
> the same as far as order of execution that t1 is processed after all existing
> events on the queue.  So I guess nextTick is basically just saving the
> overhead of having a timer?

Yes they are functionally the same, but setTimeout creates a timer, invokes libevent, and a bunch of other stuff. process.nextTick() is done all in Javascript. Also you have your parameters to setTimeout() reversed; the callback is the first param ).

On Tue, May 31, 2011 at 4:49 PM, mscdex <msc...@gmail.com> wrote:

--

Isaac Schlueter

unread,
May 31, 2011, 1:09:17 PM5/31/11
to nod...@googlegroups.com
Depending on order, probably an antipattern, yes. That being said,
nextTick does have a predictable order.

setTimeout, on the other hand, does not. Each timeout value uses its
own c-layer timer object, so if you do this:

setTimeout(A, 0)
setTimeout(B, 1)

then conceivably A might fire either before or after B.

nextTick always fires before any setTimeout timers. The process is:

1. Run all the code from top to bottom
2. If there's nothing on the event loop at all, exit.
3. Process any nextTicks
4. Wait for events (setTimeout, http requests, callbacks from fs
functions, etc.)

Mikeal Rogers

unread,
May 31, 2011, 1:20:54 PM5/31/11
to nod...@googlegroups.com
i rely on nextTick a lot actually. i think it's an emerging pattern that we'll want to preserve. requiring object state to be setup before another trip in to the event system, then using nextTick() to set defaults and lazily start is actually quite nice and, currently, very reliable. request uses it.

dhruvbird

unread,
Jun 1, 2011, 1:31:13 AM6/1/11
to nodejs

> nextTick always fires before any setTimeout timers.  The process is:
>
> 1. Run all the code from top to bottom
> 2. If there's nothing on the event loop at all, exit.
> 3. Process any nextTicks
> 4. Wait for events (setTimeout, http requests, callbacks from fs
> functions, etc.)

It seems (from the above) that if I have only a nextTick(), then it
won't be executed (unless nextTick is part of the event loop).
However, this works:

console.log("AA");
process.nextTick(function() {
console.log("BB");
});

i.e. It prints both AA & BB.

Is there more to it?

Regards,
-Dhruv.

Marak Squires

unread,
Jun 1, 2011, 1:37:54 AM6/1/11
to nod...@googlegroups.com
I doubt anyone else is doing this, but thanks to tmpvar, we use process.nextTick() in JSONloops to help keep precision for calculating Beats Per Minute. 


We use nextTick recursively so we can perform new Date().now() on every step of the event loop. This allows us to keep very accurate timing for JSONloops looper...unless someone can prove me wrong of course :-)

- Marak


--

Elijah Insua

unread,
Jun 1, 2011, 2:02:49 AM6/1/11
to nod...@googlegroups.com
> We use nextTick recursively so we can perform new Date().now() on every step of the event loop. This allows us to keep very accurate timing for JSONloops looper...unless someone can prove me wrong of course :-)

Technically, its not recursion ;).. but yeah it's about as close to a while loop that you can get without blocking

Bruno Jouhier

unread,
Jun 1, 2011, 6:05:09 AM6/1/11
to nodejs
So, you cannot really run a long computation by breaking it into small
chunks and yielding with process.nextTick between chunks. If I
understand well, this will starve the system because I/O related
callbacks (HTTP requests, fs responses) won't get their chance to run
until the computation terminates. Is this correct?

Bruno

mscdex

unread,
Jun 1, 2011, 10:01:34 AM6/1/11
to nodejs
On Jun 1, 6:05 am, Bruno Jouhier <bjouh...@gmail.com> wrote:
> So, you cannot really run a long computation by breaking it into small
> chunks and yielding with process.nextTick between chunks. If I
> understand well, this will starve the system because I/O related
> callbacks (HTTP requests, fs responses) won't get their chance to run
> until the computation terminates. Is this correct?

It's more like the opposite. If you DO break up a long computation
into smaller chunks across several ticks then that means it will block
LESS, allowing events to occur more quickly.

Bruno Jouhier

unread,
Jun 1, 2011, 12:51:51 PM6/1/11
to nodejs
If the events get dequeued as Isaac describes it, there is a
starvation problem.
As I understand it, there are two queues:

* a nextTick queue with higher priority
* an event queue with lower priority.

If I understand well, the event queue is only processed if the
nextTick queue is empty and the logic is something like:

while (nextTickQueue.length || eventQueue.length) {
if (nextTickQueue.length)
processEvent(nextTickQueue.shift());
else
processEvent(eventQueue.shift());
}


If this is the case, then a long computation that uses nextTick to
yield will maintain one element on the nextTick queue until it
completes. So two long computations will yield to each other but the
event queue will starve during that time.

But maybe the logic is different: something like:

while (nextTickQueue.length || eventQueue.length) {
var q1 = nextTickQueue;
nextTickQueue = [];
var q2 = eventQueue;
eventQueue = [];

processQueue(q1);
processQueue(q2);
}


If this is the case, then the events will be dispatched once in a
while.

The answer is in the source but I'm a bit lazy to investigate. Which
of these dequeuing variants is used? (maybe it is even something
different).

I'm actually not doing any intensive computation in my server for now.
Just being curious.

Bruno

mscdex

unread,
Jun 1, 2011, 1:12:44 PM6/1/11
to nodejs
On Jun 1, 12:51 pm, Bruno Jouhier <bjouh...@gmail.com> wrote:
> The answer is in the source but I'm a bit lazy to investigate. Which
> of these dequeuing variants is used? (maybe it is even something
> different).

https://github.com/joyent/node/blob/v0.4/src/node.js#L117

Basically there's a tick callback in js-land that is called from C++-
land at the beginning of each tick when there's functions to be
executed. Inside the callback, the length of the nextTick queue is
cached. It then iterates over the queue, calling each function.
Afterwards it does a splice to remove all the queued functions up to
the cached length, so as not to remove any new queued functions for
the next tick.

After that, any I/O or other events are fired. The process then
repeats for the next tick.

billywhizz

unread,
Jun 1, 2011, 1:15:16 PM6/1/11
to nodejs
I don't think there is any issue with starvation. timers and events
still get called if the nexttick queue is always populated...

try running this:
function next() {
console.log("next");
process.nextTick(next);
}
next();
setInterval(function() {
console.log("timer");
}, 1000);

and grep for timer when you run it:
# node nt.js | grep timer

those timers still fire. The events are handled by libev so there
isn't a "queue" in the same way as there is for nexttick. as soon as
you yield by calling nextTick and exiting your scope, then any events
in the queue should be dealt with (as far as i know). will have a dig
through the source to see if i can come up with a better
explanation...

Jorge

unread,
Jun 1, 2011, 1:28:39 PM6/1/11
to nod...@googlegroups.com

On 01/06/2011, at 18:51, Bruno Jouhier wrote:

> If the events get dequeued as Isaac describes it, there is a
> starvation problem.
> As I understand it, there are two queues:
>
> * a nextTick queue with higher priority
> * an event queue with lower priority.
>
> If I understand well, the event queue is only processed if the
> nextTick queue is empty and the logic is something like:
>
> while (nextTickQueue.length || eventQueue.length) {
> if (nextTickQueue.length)
> processEvent(nextTickQueue.shift());
> else
> processEvent(eventQueue.shift());
> }

No. It's not so. When node grabs the nextTick queue to service it, it has a finite length (say 20 items), any additional items that might be added to the nextick queue while it's being serviced, won't be serviced until the next tick:

So it will be more like so:

1.- grab the nextTick queue .length.
2.- remove and service the first (length) items in it. (some more items might be added as a result, but these won't be serviced yet)
3.- service other events: timers, i/o, async, etc.
4.- goto 1

> (...)

--
Jorge.

Bruno Jouhier

unread,
Jun 1, 2011, 4:16:15 PM6/1/11
to nodejs
Thanks Jorge,

This corresponds more or less to the second loop that I posted (the
one that reallocates the queues).

I was a bit confused by the statement: "nextTick always fires before
any setTimeout timers". I think that it should read "nextTick always
fires before any setTimeout timers created during the same tick". A
timeout that was initiated during a previous tick may fire before
nextTick!

Is this right?

Bruno

Jorge

unread,
Jun 1, 2011, 4:39:04 PM6/1/11
to nod...@googlegroups.com
On 01/06/2011, at 22:16, Bruno Jouhier wrote:

> Thanks Jorge,
>
> This corresponds more or less to the second loop that I posted (the
> one that reallocates the queues).
>
> I was a bit confused by the statement: "nextTick always fires before
> any setTimeout timers". I think that it should read "nextTick always
> fires before any setTimeout timers created during the same tick". A
> timeout that was initiated during a previous tick may fire before
> nextTick!
>
> Is this right?

Yes it is. Given this:

setTimeout(f, 0);
process.nextTick(g);

function g () { process.nextTick(h) }

- g() will run before f(), but
- h() may run before or after f().

Oh, and wrt timers: node.js is *the*only* JS platform that I know where this

setTimeout( f, 1 );
setTimeout( g, 2 );

may eventually trigger g() before f(). I consider it a bug, but ry thinks different... :-)
--
Jorge.

Mikeal Rogers

unread,
Jun 1, 2011, 4:44:21 PM6/1/11
to nod...@googlegroups.com
i would also consider that a bug.

Isaac Schlueter

unread,
Jun 1, 2011, 5:03:53 PM6/1/11
to nod...@googlegroups.com
On Wed, Jun 1, 2011 at 13:39, Jorge <jo...@jorgechamorro.com> wrote:
> setTimeout(f, 0);
> process.nextTick(g);
>
> function g () { process.nextTick(h) }
>
> - g() will run before f(), but
> - h() may run before or after f().

That is correct. Timers are checked after nextTick callbacks, but any
nextTick callbacks added by that batch of nextTick callbacks won't be
processed in the same tick as their parents, so those timers may fire.

> Oh, and wrt timers: node.js is *the*only* JS platform that I know where this
>
> setTimeout( f, 1 );
> setTimeout( g, 2 );
>
> may eventually trigger g() before f(). I consider it a bug, but ry thinks different... :-)

Actually, this has never been guaranteed by any JavaScript platform
that I'm aware of, and at least in IE, Firefox, and Safari circa 2008,
it was quite common to see low-valued timers firing in that way. I
have been bitten hard by the assumption that timers will always be in
a predictable order. On most browsers, any timeout value less than
some minimum value is silently changed to that minimum (50ms, last I
checked, which was quite some time ago).

Node's setTimeout is remarkably precise, in fact.

Bruno Jouhier

unread,
Jun 1, 2011, 5:07:31 PM6/1/11
to nodejs
I'd be on ry's side here. I don't think that people should rely on
assumptions like these when writing non-deterministic code.

Jorge

unread,
Jun 2, 2011, 7:55:03 AM6/2/11
to nod...@googlegroups.com
On 01/06/2011, at 23:03, Isaac Schlueter wrote:
> On Wed, Jun 1, 2011 at 13:39, Jorge <jo...@jorgechamorro.com> wrote:
>
>> Oh, and wrt timers: node.js is *the*only* JS platform that I know where this
>>
>> setTimeout( f, 1 );
>> setTimeout( g, 2 );
>>
>> may eventually trigger g() before f(). I consider it a bug, but ry thinks different... :-)
>
> Actually, this has never been guaranteed by any JavaScript platform
> that I'm aware of, and at least in IE, Firefox, and Safari circa 2008,
> it was quite common to see low-valued timers firing in that way.

I've never seen that happen in any browser, only in node.js.

Here's a test.js for node and a bookmarklet to run the test in any browser:

<https://github.com/xk/nodeSnippets/blob/master/timers_ORDER.js>

node.js fails but I've yet to find a browser that fails.

> I
> have been bitten hard by the assumption that timers will always be in
> a predictable order. On most browsers, any timeout value less than
> some minimum value is silently changed to that minimum (50ms, last I
> checked, which was quite some time ago).

Yes, but that's another story, isn't it ?
--
Jorge.

Jorge

unread,
Jun 2, 2011, 7:57:25 AM6/2/11
to nod...@googlegroups.com
On 01/06/2011, at 23:07, Bruno Jouhier wrote:

> I'd be on ry's side here. I don't think that people should rely on
> assumptions like these when writing non-deterministic code.

OTOH, if that's what every browser out there does, then it's the expected behaviour, then node.js should perhaps (better) do it that way too.

--
Jorge.

Jorge

unread,
Jun 2, 2011, 8:14:00 AM6/2/11
to nod...@googlegroups.com

Also, don't you expect nextTick()s to fire orderly ? I do !
--
Jorge.

Matt

unread,
Jun 2, 2011, 8:48:32 AM6/2/11
to nod...@googlegroups.com
No. I think you need to get used to the concept of an event loop and how things work in the real world. This is effectively threading, and there's no order guarantees.

Matt.

mscdex

unread,
Jun 2, 2011, 11:53:47 AM6/2/11
to nodejs
On Jun 2, 8:48 am, Matt <hel...@gmail.com> wrote:
> No. I think you need to get used to the concept of an event loop and how
> things work in the real world. This is effectively threading, and there's no
> order guarantees.

I like how nextTick behaves currently and how it guarantees execution
order for queued callbacks. I wouldn't really think of nextTick as
threading though...

Isaac Schlueter

unread,
Jun 2, 2011, 5:46:56 PM6/2/11
to nod...@googlegroups.com
There are no threads in JavaScript-land in Node. There are important
differences between threads and an event loop. (That being said,
there are threads that put code onto the event loop, so if you're
doing a lot of FS or network stuff, it's not predictably ordered,
because it's threads under the hood.)

nextTick is predictably ordered because it is explicitly just "Put
this function on the event loop to run at the end of this pass, at the
highest priority." It's for cases where you want to mimic async
behavior, but not take unnecessary time (for instance, if you find
something from cache that would normally require a db lookup.)

That browser setTimeout test doesn't actually run into any cases that
are particularly tricky. I've seen this behavior on the Yahoo
Application Platform front-end code where we had several thousand
events firing over the course of a session, making heavy use of
setTimeout(fn, 0). In the first iteration, we relied on certain
things being in-order, and had strange bugs as a result of the order
being unpredictable <1% of the time, only when there were many many
dom nodes being updated around the same time.

I was never able to reliably reproduce it in any minified contrived
test-case. So, I guess there's an element of FUD in what I'm saying
here, and I apologize for that. My only defense is that I do have
first-hand experience that it was a real issue we saw in multiple
browsers, and refactoring the code to accept out-of-order setTimeout
firing made the problems disappear.

Also, it's really tricky and complex to guarantee order. In the end,
it's not worth the effort.

Matt

unread,
Jun 2, 2011, 7:51:24 PM6/2/11
to nod...@googlegroups.com
I know it's not *really* threading, I know how this stuff works (I wrote half of perl's Danga::Socket library after all, particularly the timers stuff). But expecting guaranteed execution order is as foolish as expecting setTimeout() calls to fire in *exactly* the number of milliseconds you asked for them to fire.
Reply all
Reply to author
Forward
0 new messages