setImmediate vs. nextTick

后端 未结 7 655
野的像风
野的像风 2020-11-22 12:26

Node.js version 0.10 was released today and introduced setImmediate. The API changes documentation suggests using it when doing recursive nextTick

相关标签:
7条回答
  • 2020-11-22 13:01

    Some great answers here detailing how they both work.

    Just adding one that answers the specific question asked:

    When should I use nextTick and when should I use setImmediate?


    Always use setImmediate.


    The Node.js Event Loop, Timers, and process.nextTick() doc includes the following:

    We recommend developers use setImmediate() in all cases because it's easier to reason about (and it leads to code that's compatible with a wider variety of environments, like browser JS.)


    Earlier in the doc it warns that process.nextTick can lead to...

    some bad situations because it allows you to "starve" your I/O by making recursive process.nextTick() calls, which prevents the event loop from reaching the poll phase.

    As it turns out, process.nextTick can even starve Promises:

    Promise.resolve().then(() => { console.log('this happens LAST'); });
    
    process.nextTick(() => {
      console.log('all of these...');
      process.nextTick(() => {
        console.log('...happen before...');
        process.nextTick(() => {
          console.log('...the Promise ever...');
          process.nextTick(() => {
            console.log('...has a chance to resolve');
          })
        })
      })
    })
    

    On the other hand, setImmediate is "easier to reason about" and avoids these types of issues:

    Promise.resolve().then(() => { console.log('this happens FIRST'); });
    
    setImmediate(() => {
      console.log('this happens LAST');
    })
    

    So unless there is a specific need for the unique behavior of process.nextTick, the recommended approach is to "use setImmediate() in all cases".

    0 讨论(0)
  • 2020-11-22 13:06

    Use setImmediate if you want to queue the function behind whatever I/O event callbacks that are already in the event queue. Use process.nextTick to effectively queue the function at the head of the event queue so that it executes immediately after the current function completes.

    So in a case where you're trying to break up a long running, CPU-bound job using recursion, you would now want to use setImmediate rather than process.nextTick to queue the next iteration as otherwise any I/O event callbacks wouldn't get the chance to run between iterations.

    0 讨论(0)
  • 2020-11-22 13:06

    In simple terms, process.NextTick() would executed at next tick of event loop. However, the setImmediate, basically has a separate phase which ensures that the callback registered under setImmediate() will be called only after the IO callback and polling phase.

    Please refer to this link for nice explanation: https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c

    0 讨论(0)
  • 2020-11-22 13:09

    As an illustration

    import fs from 'fs';
    import http from 'http';
    
    const options = {
      host: 'www.stackoverflow.com',
      port: 80,
      path: '/index.html'
    };
    
    describe('deferredExecution', () => {
      it('deferredExecution', (done) => {
        console.log('Start');
        setTimeout(() => console.log('TO1'), 0);
        setImmediate(() => console.log('IM1'));
        process.nextTick(() => console.log('NT1'));
        setImmediate(() => console.log('IM2'));
        process.nextTick(() => console.log('NT2'));
        http.get(options, () => console.log('IO1'));
        fs.readdir(process.cwd(), () => console.log('IO2'));
        setImmediate(() => console.log('IM3'));
        process.nextTick(() => console.log('NT3'));
        setImmediate(() => console.log('IM4'));
        fs.readdir(process.cwd(), () => console.log('IO3'));
        console.log('Done');
        setTimeout(done, 1500);
      });
    });
    

    will give the following output

    Start
    Done
    NT1
    NT2
    NT3
    TO1
    IO2
    IO3
    IM1
    IM2
    IM3
    IM4
    IO1
    

    I hope this can help to understand the difference.

    Updated:

    Callbacks deferred with process.nextTick() run before any other I/O event is fired, while with setImmediate(), the execution is queued behind any I/O event that is already in the queue.

    Node.js Design Patterns, by Mario Casciaro (probably the best book about node.js/js)

    0 讨论(0)
  • 2020-11-22 13:10

    In the comments in the answer, it does not explicitly state that nextTick shifted from Macrosemantics to Microsemantics.

    before node 0.9 (when setImmediate was introduced), nextTick operated at the start of the next callstack.

    since node 0.9, nextTick operates at the end of the existing callstack, whereas setImmediate is at the start of the next callstack

    check out https://github.com/YuzuJS/setImmediate for tools and details

    0 讨论(0)
  • 2020-11-22 13:12

    I recommend you to check docs section dedicated for Loop to get better understanding. Some snippet taken from there:

    We have two calls that are similar as far as users are concerned, but their names are confusing.

    • process.nextTick() fires immediately on the same phase

    • setImmediate() fires on the following iteration or 'tick' of the
      event loop

    In essence, the names should be swapped. process.nextTick() fires more immediately than setImmediate(), but this is an artifact of the past which is unlikely to change.

    0 讨论(0)
提交回复
热议问题