JS中的事件循环与宏任务、微任务

403 阅读1分钟

事件循环

  JS是单线程的,当有异步任务时会交给系统内核。操作完成时内核会通知Node.js将任务添加到轮询队列中等待执行。

  所有的同步代码都会优先在主线程中执行,执行完后才会开始执行异步任务。所以定时器的时间不是完全可靠的,如下面的代码:

for( let i =0 ;i<10000000000;i++ ){}
setTimeout(()=>console.log('异步代码执行完了'),0) // 可以看出定时器是在循环后执行,而不是0毫秒后执行

  下图是代码执行的顺序: image.png   同步代码都执行完毕后,会先看有没有定时器到时间,有就执行(Timer)。接着执行IO、文件读取、网络请求等(I/O callbacks)。idle,prepare阶段是内部执行的,不用管。poll就是轮询等待前面的I/O任务执行结果,如果有新的I/O任务,将会继续进入Pending阶段。setImmediate中的回调会在这个阶段执行。Close callbacks阶段执行各种close事件的回调,如socket.on('close',()=>...)。接着查看是否还有异步任务,有就执行。一直循环到没有异步任务就完成脚本。顺序如下:

  • setTimeout、setInterval
  • I/O任务
  • setImmediate
  • close

宏任务、微任务

  事件循环的过程中,先执行宏任务,执行宏任务过程中如果有可执行的微任务,就执行微任务,没有就继续执行新的宏任务。

image.png

宏任务:

  • script( 整体代码)
  • setTimeout、setInterval
  • setImmediate
  • I/O、UI 交互事件 微任务:
  • Promise
  • MutaionObserver、
  • process.nextTick(Node.js 环境)