阅读 58

简述浏览器端的事件循环--EventLoop

这是我参与更文挑战的第16天,活动详情查看:更文挑战

什么是单线程?

js语言是单线程的,同一时刻只能做一件事情

JavaScript为什么是单线程?

浏览器JS的作用是操作DOM,决定了它只能是单线程,否则会带来很复杂的同步问题,比如:假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准。为了协调事件、用户交互、UI渲染和网络请求等行为,防止主线程进入阻塞,eventloop的方案应运而生。eventloop包含两类:一类是基于 Browsing Context,一类是基于Worker,二者是独立的。这里主要说一下基于浏览器端的事件循环。

任务队列(task queue)

事件循环是使用任务队列的机制来实现的。一个eventloop中,可以有一个或多个任务队列(task queue),一个任务队列是一系列有序任务(task)的集合(set)。

广义任务为两种,一种是同步任务,另一种是异步任务。

  1. 所有同步任务都在主线程上执行,形成一个执行栈;
  2. 主线程之外,还有一个任务队列,只要异步任务有了任务运行结果,就在任务队列之中放置一个事件;
  3. 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里边有哪些事件,哪些对应的异步任务,于是结束等待状态,进行执行栈,开始执行。
  4. 主线程不断重复上面的第3步。

同步任务:

  • 输出
  • 变量的声明
  • 同步函数等

异步任务:

  • setTimeout和setInterval
  • DOM事件
  • Promise
  • ajax
  • fileReader
  • 异步函数等

宏任务和微任务

宏任务:script(整体代码),setTimeout , setIntval , setImmediate , I/O , UI 交互, rending, postMessage, MessageChannel, requestAnimationFrame;
微任务:process.nextick , promise , Object.observe , MutationObserver;

  1. 宏任务进入主线程,执行过程中就会收集微任务加入微任务队列;
  2. 宏任务执行完毕后,立马执行微任务的任务(依次执行),微任务队列执行过程中将再次收集宏任务,并加入宏任务队列;
  3. 反复执行 1,2 步骤。

也就是: 宏任务 -> 微任务 -> 渲染,然后重复

注意:
每一轮事件循环执行一个宏任务和所有微任务;
任务队列,一定会保持先进先出的顺序执行。

文章分类
前端
文章标签