美文网首页
任务队列之nodejs中的process.nextTick和se

任务队列之nodejs中的process.nextTick和se

作者: 我叫傻先生 | 来源:发表于2017-09-21 20:19 被阅读0次

    原文:http://www.ruanyifeng.com/blog/2014/10/event-loop.html

    process.nextTick:是当执行栈的任务做完了后,将要进行下一次Event Loop(主线程读取"任务队列")之前,例如:

    process.nextTick(function A() {
      console.log(1);
      process.nextTick(function B(){console.log(2);});
    });
    setTimeout(function timeout() {
      console.log('TIMEOUT FIRED');
    }, 0)
    // 1
    // 2
    // TIMEOUT FIRED
    

    由于process.nextTick方法指定的回调函数,总是在当前"执行栈"的尾部触发,所以不仅函数A比setTimeout指定的回调函数timeout先执行,而且函数B也比timeout先执行。这说明,如果有多个process.nextTick语句(不管它们是否嵌套),将全部在当前"执行栈"执行
    setImmediate:是setImmediate方法则是在当前"任务队列"的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行

    setImmediate(function A() {
      console.log(1);
      setImmediate(function B(){console.log(2);});
    });
    setTimeout(function timeout() {
      console.log('TIMEOUT FIRED');
    }, 0);
    

    哪个回调函数先执行呢?答案是不确定。运行结果可能是1--TIMEOUT FIRED--2,也可能是TIMEOUT FIRED--1--2。
    令人困惑的是,Node.js文档中称,setImmediate指定的回调函数,总是排在setTimeout前面。实际上,这种情况只发生在递归调用的时候。

    setImmediate(function (){
      setImmediate(function A() {
          console.log(1);
          setImmediate(function B(){console.log(2);});
      });
      setTimeout(function timeout() {
        console.log('TIMEOUT FIRED');
      }, 0);
    });
    // 1
    // TIMEOUT FIRED
    // 2
    

    setImmediate和setTimeout被封装在一个setImmediate里面,它的运行结果总是1--TIMEOUT FIRED--2,这时函数A一定在timeout前面触发。至于2排在TIMEOUT FIRED的后面(即函数B在timeout后面触发),是因为setImmediate总是将事件注册到下一轮Event Loop,所以函数A和timeout是在同一轮Loop执行,而函数B在下一轮Loop执行。
    我们由此得到了process.nextTick和setImmediate的一个重要区别:多个process.nextTick语句总是在当前"执行栈"一次执行完,多个setImmediate可能则需要多次loop才能执行完。事实上,这正是Node.js 10.0版添加setImmediate方法的原因,否则像下面这样的递归调用process.nextTick,将会没完没了,主线程根本不会去读取"事件队列"!

    process.nextTick(function foo() {
      process.nextTick(foo);
    });
    

    相关文章

      网友评论

          本文标题:任务队列之nodejs中的process.nextTick和se

          本文链接:https://www.haomeiwen.com/subject/xiutextx.html