likes
comments
collection
share

EventLoop事件循环个人理解

作者站长头像
站长
· 阅读数 26

是什么?

浏览器的每个渲染进程都有一个主线程,主线程非常繁忙,需要处理dom、计算css、计算布局、执行js代码、响应鼠标键盘输入事件等任务。要让这么多不同类型的任务有条不紊的执行,就需要一个任务管理系统,这个任务管理系统就是事件循环系统EventLoop事件循环个人理解

如何执行任务?

EventLoop事件循环个人理解

常见宏任务

常见宏任务包含两大类:

  1. 延迟任务,比如定时器
  2. 异步回调任务,比如点击、滚动、键盘按下等输入事件,Ajax请求等

延迟型任务和异步回调任务区别

  • 延迟型任务主要指定时器任务,也包括浏览器的一些延迟型任务。这类任务一般对执行时效比较敏感,如果只是简单的扔进任务队列,那么很可能执行时机会有问题。所以除了基础的任务队列外,还存在一个延迟任务队列。当前宏任务执行完毕后,主线程并不会立刻去执行下一个宏任务,而是检查延迟任务队列中是否有到期需要执行的任务,如果有就取出这些到期任务全部执行。我们设置定时器返回的id就是这个任务在延迟任务队列的一个唯一标识,如果需要取消延迟任务,则只需要把对应id的任务从延迟队列中移除即可。当然,即使这样设计,如果上一个宏任务占用主线程时间过久,仍然会导致延迟任务执行时机推迟,应当避免在延迟任务之前执行长期阻塞主线程的代码。
  • 异步回调任务主要指ajax请求,事件响应等,当我们发送一个ajax请求并设置回调函数时,会发生下列几步:
    1. 渲染进程通知网络进程请求对应资源
    2. 渲染进程任务继续执行
    3. 请求结束,网络进程通过IPC告诉渲染进程请求结果
    4. 渲染进程重的IO进程将结果封装为任务放进任务队列
    5. 主线程取出异步回调任务执行

异步回调和同步回调

同步回调指在主函数体内执行完毕的回调,例如:

function foo(cb) {
  console.log('start')
  cb();
  console.log('end')
}

// 同步回调,回调函数在主函数体内执行完毕
function _sync() {
  console.log(2333)
}

// 异步回调,回调函数在主函数体外执行完毕
function _async() {
  setTimeout(function () {
    console.log(2333)
  }, 100)
}

// start
// 2333
// end
foo(_sync)

// start
// end
// 2333
foo(_async)

常见微任务

  • Mutation Observer
  • Promise

宏任务和微任务的关系

每个宏任务都会维护一个微任务队列,在宏任务代码执行完毕后,不会立刻退出主线程,而是检查自己的微任务队列是否为空(checkpoint),不为空就需要逐个执行清空。如果在这个过程中产生了新的微任务,则会继续执行,直到清空为止。

为什么要这么处理? 为了保证异步任务执行的时效性,如果插入到宏任务队列中则可能会受影响

转载自:https://juejin.cn/post/6910877000810889229
评论
请登录