|

Aimee

Write the Code. Change the World.

事件循环

· 分享镜#h5#node

宏任务和微任务

宏任务

指任务队列中的任务,如下:

  • 整体的script代码(浏览器 和node)
  • setTimeout (浏览器 和node)
  • setInterval (浏览器 和node)
  • setImmediate (node)
  • requestAnimationFrame (浏览器)
  • i/o (node)

setImmediate 可代替setTimeout('fun',0) ,并解决时间不准的问题 ​

微任务

指需要异步执行的任务,执行时机是在主任务执行之后,当前宏任务结束之前,如下:

  • promise.then catch finally (浏览器 和node)
  • prcess.nextTick (node)
  • MutationObserver (浏览器)

MutationObserver用于监听dom的改变,并在说有改变结束后 以数组的方式返回记录的结果 ​ 为什么需要微任务? 因为js是单线程的,所有任务都按照同一优先级顺序执行,会造成一些优先级任务的实时性问题,所以会出现微任务,通过将实时性要求较高的任务放在微任务队列中,从而保证高优先级任务的实时性要求。

同步任务和异步任务

广义分为 同步任务和异步任务

同步任务

指在主线程上排队执行的任务,一次只执行一个同步任务,执行完之后才会执行下一个同步任务。

异步任务

不进入主线程,而进入任务队列,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。 ​

为什么会有异步任务? 因为js是单线程的,如果只有同步任务,只有当前任务执行完之后,才会执行下一个任务,其他任务都处于等待状态,会造成下一个任务等待时间较长,通过异步任务就可以解决这个问题。

事件循环

浏览器的事件循环

同步异步: 同步和异步分别由event queue 和event table,当遇到同步的任务后,加入到同步的event queue中,如果有异步的任务加入到event table中,同步任务执行完后,通知对应的异步event table执行,执行完成后,再执行event queue 中的下一个任务。这样的执行过程形成了 event loop. ​ 宏任务和微任务: js线程先执行当前宏任务,并同时开启一个微任务队列,遇到微任务时,先放到微任务队列中,宏任务执行完成看是否有微任务,如果有微任务先执行微任务队列,微任务队列执行完成后,再开启新的一轮宏任务。

示例:

setTimeout(() => {
    //执行后 回调一个宏事件
    console.log('内层宏事件3')
}, 0)
console.log('外层宏事件1');

new Promise((resolve) => {
    console.log('外层宏事件2');
    resolve()
}).then(() => {
    console.log('微事件1');
}).then(()=>{
    console.log('微事件2')
})

执行上面的代码过程:

  • 将setTimeout到添加宏任务队列中;
  • 执行"外层宏事件1" console
  • 执行promise中的"外层宏事件2" console;
  • 将then 中的"微事件1"中添加到微任务队列中;
  • 将then中的"微事件2"中添加到微任务队列中;
  • 执行微任务队列内容,"微事件1"、"微事件2" console;
  • 进行宏任务队列中的 "内层宏事件3" console;

nodejs 的事件循环

​ node.js 中的事件循环分为各个阶段, 包括

  • 定时器 timers
  • io回调 io callbacks
  • idle prepare 系统内部
  • 轮询 检索新的io事件 poll
  • 检测 setImmediate 回调 check
  • 连接关闭 回调 如socket.on('close',...)

各个阶段组成一个大的循环,每个阶段内部都有一个fifo队列来执行回调。当事件循环进入给定的阶段时,它将执行于该阶段的任何操作,然后执行该阶段队列中的回调,直到队列用尽或最大回调已执行。当该队列已用尽或已达到最大回调限制,事件循环将移动到下一个阶段。 ​ 浏览器和nodejs的事件循环主要区别: 浏览器的微任务是在对应的宏任务中执行的,nodejs的微任务是在各个阶段之间执行的。

评论0

登录后参与评论。

还没有评论,来抢沙发吧。

回到顶部