美文网首页
事件循环

事件循环

作者: yanmingfei | 来源:发表于2019-10-13 10:45 被阅读0次

    Node事件环

    • 微任务的概念(promise.then process.nextTick)
    • timers 时间 setTimeout setInterval
    • poll 轮询 i/o回调 fs.readFile()
    • check setImmediate方法

    默认会从上到下依次执行,如果代码执行到poll后,发现check阶段没有,那就在poll阶段等待(时间到没到)时间到达到清空代码执行。
    和浏览器不太一样的是,浏览器是在执行宏任务就把内部的微任务优先执行。
    node则是执行只要队列发生切换时就会执行微任务。

    setTimeout(()=>{
      console.log('timeout')
    })
    console.log('start');
    process.nextTick(()=>{
      console.log('nextTick');
    });
    Promise.resolve().then(data=>{
      console.log('then')
    })
    

    代码执行顺序为先执行主任务,console.log('start');然后开始切换时间队列定时器,只要队列发生切换就会执行微任务。所以会执行nextTick()和Promise的then方法,再执行定时器中的代码。
    看到这里大家就会就觉得和浏览器的事件循环好像一模一样呀。其实不然,有时会有差异。这个千万小心。

    setTimeout(()=>{
      console.log('timeout1')
      process.nextTick(()=>{
        console.log('nextTick2');
      });
    })
    console.log('start');
    process.nextTick(()=>{
      console.log('nextTick1');
      setTimeout(()=>{
        console.log('timeout2')
      })
    });
    

    这段代码的执行结果可以是
    第一种情况:
    start nextTick1 timeout1 nextTick2 timeout2
    第二种情况
    start nextTick1 timeout1 timeout2 nextTick2 这种情况在debug下,我们刻意延迟时间,让代码执行。最终会发现执行结果如下。

    setTimeout(()=>{
      console.log('timeout1')
      process.nextTick(()=>{
        console.log('nextTick2');
      });
    })
    console.log('start');
    process.nextTick(()=>{
      console.log('nextTick1');
      setTimeout(()=>{
        console.log('timeout2')
      })
    });
    
    setImmediate(()=>{
      console.log('setImmediate');
    });
    setTimeout(()=>{
      console.log('setTimeout');
    })
    

    这段代码的执行结果也有很多情况
    第一种情况
    start nextTick1 timeout1 nextTick2 setImmediate setTimeout timeout2
    第二种情况
    start nextTick1 timeout1 setTimeout nextTick2 setImmediate timeout2
    第三种情况
    start nextTick1 timeout1 setTimeout timeout2 nextTick2 setImmediate

    切换队列的情况: 把队列清空、如果执行大量的回调,超过了最大限制,就会切换队列

    经典面试题

    const fs = require('fs');
    fs.readFile('./package.json','utf-8',()=>{
      setTimeout(()=>{
        console.log('setTimeout');
      });
      setImmediate(()=>{
        console.log('setImmediate');
      });
    })
    

    执行结果为setImmediate setTimeout。这是因为进入IO之后随之进入check阶段,然后才会进入下次事件循环中。

    相关文章

      网友评论

          本文标题:事件循环

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