美文网首页
浏览器的事件循环机制(Event Loop)

浏览器的事件循环机制(Event Loop)

作者: 凯凯frank | 来源:发表于2020-02-09 23:56 被阅读0次

js是一门单线程非阻塞的脚本语言
单线程意味着,js在执行的时候,只有一个主线程来处理所有的任务。
非阻塞则是当代码需要进行一项异步任务(如I/O事件、网络请求)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果后,将注册的回调函数放入任务队列中,等待主线程空闲的时候(调用栈被清空),再根据一定的规则读取任务队列中的任务。

任务队列分为两种:宏任务(macro task)和微任务(micro task)。

宏任务和微任务

宏任务,macrotask,也叫tasks。
包括:script全部代码、setTimeout、setInterval、requestAnimationFrame (浏览器独有)、I/O、UI rendering (浏览器独有)

微任务,microtask,也叫jobs。
包括:Promise、ajax、Object.observe(废弃)、MutationObserver

事件执行顺序(也可以直接看下面的简单版本):

  1. 执行全局的同步代码,全局Script代码执行完毕后,调用栈Stack会清空;
  2. 依次从微队列microtask queue中取出位于队首的回调任务,放入调用栈Stack中执行,直到直到把microtask queue中的所有任务都执行完毕。(如果在执行microtask的过程中,又产生了microtask,那么会加入到队列的末尾,也会在这个周期被调用执行) 。microtask queue中的所有任务都执行完毕,此时microtask queue为空队列,调用栈Stack也为空;
    3.如果需要的话,渲染页面;
    4.取出宏队列macrotask queue中位于队首的任务,放入Stack中执行;执行完毕后,调用栈Stack为空;
    重复第2-4步骤;
    ......

简单的来说,事件循环是指: 先执行一次宏任务,然后清空微任务列表,然后需要的话,渲染页面,然后循环上面的步骤。如下图


eventLoop.png

练习题目

console.log(1);

setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => {
    console.log(3)
  });
});

new Promise((resolve, reject) => {
  console.log(4)
  resolve(5)
}).then((data) => {
  console.log(data);
}).then((data) => {
  console.log('another');
})

setTimeout(() => {
  console.log(6);
})

console.log(7);

正确答案

1
4
7
5
another
2
3
6

解析:

首先1 4 7属于全局的同步代码,先执行。注意new Promise的时候也属于同步执行。
然后再执行微任务队列中所有的任务,即5, 此时又向微任务队列中添加了一个任务,一并在此周期内被调用执行,即 another
然后要取出一个宏任务队列中的任务,即2
然后再执行微任务队列中所有的任务, 即3
然后要取出一个宏任务队列中的任务,即6

相关文章

网友评论

      本文标题:浏览器的事件循环机制(Event Loop)

      本文链接:https://www.haomeiwen.com/subject/tlloxhtx.html