浏览器中的事件循环

浏览器中的事件循环

     为了协调浏览器中event,user interaction,script,rendering,networking等,user agent必须使用事件循环(event loops)。

To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. Each agent has an associated event loop.

  • 事件(event):PostMessage, MutationObserver 等

  • 用户交互(user interaction): click, onScroll 等

  • 渲染(rendering): 解析 dom,css 等

  • 脚本(script):js 脚本执行

事件循环的本质

在浏览器或者 nodejs 环境中,运行时对 js 脚本的调度方式就叫做事件循环。事件循环遵循的原则(会在文章最后的例子中详细解释):

1.任务队列一定会保持先进先出的顺序执行。

2.每轮事件循环执行一个宏任务和所有的微任务。

3.任务队列一定会保持先进先出的顺序执行。

Javascript 为什么是单线程的?

       浏览器 js 的作用是操作 DOM,这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定 JavaScript 同时有两个线程,一个线程在某个 DOM 节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

任务队列

       单线程就意味着所有任务需要排队,如果因为任务 cpu 计算量大还好,但是 I/O 操作 cpu 是闲着的。所以 js 就设计成了一门异步的语言,不会做无畏的等待。任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为 Event Loop(事件循环)。

宏任务与微任务

除了广义的同步任务和异步任务,JavaScript 单线程中的任务队列中的任务可以细分为宏任务(macrotask)和微任务(microtask)。

  • macrotask: script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。

  • microtask:process.nextTick, Promise, Object.observe, MutationObserver。

  1. 宏任务进入主线程,执行过程中会收集微任务加入微任务队列。

  2. 宏任务执行完成之后,立马执行微任务中的任务。微任务执行过程中将再次收集宏任务,并加入宏任务队列。

  3. 反复执行 1,2 步骤

setTimeout(() => {
  console.log("setTimeout");
}, 0);
​
Promise.resolve().then(() => {
  console.log("promise");
});
​
console.log("main");
​
// 1. main 2. promise 3. setTimeout

异步函数包括:

process.nextTick (Node) Promise.then() catch finally Object.observe MutationObserver

每轮事件循环执行一个宏任务和所有的微任务。

setTimeout(() => {
  Promise.resolve().then(() => {
    console.log("promise");
  });
}, 0);

Promise.resolve().then(() => {
  setTimeout(() => {
    console.log("setTimeout");
  }, 0);
});

console.log("main");


//执行结果为: main    promise    setTimeout

任务队列一定会保持先进先出的顺序执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值