首页 > 其他 > 详细

宏任务和微任务

时间:2021-04-07 12:31:11      阅读:19      评论:0      收藏:0      [点我收藏+]

宏任务和微任务

常见的面试题:

console.log(‘start‘)

setTimeout(()=>{
console.log(‘setTimeout‘)
},0)

new Promise((resolve)=>{
console.log("promise");
resolve();
}).then(()=>{
console.log("then1");
}).then(()=>{
console.log("then2");
})

console.log("end");

 

它的顺序是

start 
promise
end
then1
then2
setTimeout

  

  Event Loop中,每一次循环称为tick,每一次tick的任务如下:

  执行栈选择最先进入队列的宏任务,执行其同步代码直至结束;

  检查是否存在微任务,有则会执行微任务队列为空;

  如果宿主为浏览器,可能会渲染页面;

  开始下一轮tick,执行宏任务中的异步代码;

 

  ES6规范中,microtask称为jobs, macrotask称为task,宏任务是由宿主发起的,而微任务由JavaScript自身发起。

 

  setImmediate 和 process.nextTick 为Node环境下常用的方法,所以基于Node宿主分析。

  ( Node.js是运行在服务端的js,虽然用到也是v8引擎,但由于服务目的和环境不同,导致了它的API和原生JS有些区别,其EventLoop还要处理一些I/O,比如新的网络连接等。)

 

 执行顺序如下:

     1、timers: 执行setTimeout和setInterval的回调。

     2、pending callbacks:执行延迟到下一个循环迭代的I/O回调。

     3、idle prepare:仅系统内部使用。

     4、poll:检索新的I/O事件;执行与I/O事件相关的回调。

     5、check: setImmediate在这里执行。

     6、close callbacks: 一些关闭的函调函数

 

 setImmediate和setTimeout

console.log("outer");
setTimeout(() => {
     setTimeout(() => {
        console.log("setTimeout");
     },0);

     setImmediate(() => {
        console.log("setImmediate")
      })
},0)

  其执行顺序为:

   1、外层是一个setTimeout,所以执行它的回调函数已经在timers阶段了。

   2、处理里边的setTimeout,因为本次循环的timers正在执行,所以其回调其实加到了下一级timers阶段

   3、处理里边的setImmediate,将它的回调加入check阶段的队列。

   4、外层timers阶段处理完,进入pending callbacks,idle,prepare,poll,这几个队列都是空的,所以继续住下到了check阶段,发现了setImmediate的回调,拿出来执行

   5、然后是close callbacks,队列是空的,跳过

 

  在Node里边对setTimeout的特殊处理,setTimeout(fn, 0)会被强制改为setTimeout(fn, 1)

      1、遇到setTimeout,虽然设置的是0毫秒触发,但是被node.js强制改为1毫秒,塞入timers阶段。

      2、遇到setImmediate塞入check阶段。

      3、同步代码执行完毕,进入Event  Loop

      4、先进入timers阶段,检查当前时间过去了1毫秒没有,如果过了1毫秒,满足setTimeout条件,执行回调,如果没过14毫秒,跳过。

      5、跳过空的阶段,进入check阶段,执行setImmediate

 

     可见,1毫秒是个关键点,所以,setImmediate不一定在setTimeout之前执行了。

 

   promise process.nextTick

        因为 process.nextTick 为node环境下的方法,是一个特殊的异步API,其不属于任何的Event Loop阶段。事实上Node在遇到这个API时,Event Loop根本不会继续进行,会马上停下来执行process.nextTick( ), 这个执行完才会继续Event Loop。

        所以,nextTick 和 Promise 同时出现,肯定是nextTick先执行,原因是nextTick的队列比Promise队列优先级更高。

       vm.$nextTick 接受一个回调函数作为参数,用于将回调延迟到下次DOM更新周期之后执行。这个API就是基于事件循环实现的。下次DOM更新就是下次微任务执行时更新DOM,而vm.$nextTick就是将回调函数添加到微任务中。

宏任务和微任务

原文:https://www.cnblogs.com/zhishiyv/p/14626630.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!