目录

  • 事件循环机制
  • 宏任务与微任务
  • 实例分析
  • 参考

1.事件循环机制

浏览器执行JS代码大致可以分为三个步骤,而这三个步骤的往复构成了JS的事件循环机制(如图)。

第一步:主线程(JS引擎线程)中执行JS整体代码或回调函数(也就是宏任务),执行过程中会将对象存储到堆(heap)中,将函数的参数和局部变量加入到栈(stack)中,执行完毕后会释放堆或退出栈。执行完这个宏任务后,会判断微任务队列(microtask queue)是否为空,如果不为空,则会将所有的微任务依次取出并执行。如果在这个过程中触发了任何 Web APIs 将进行第二步操作。

第二步:调用 Web API,并在合适的时候将回调函数加入到事件回调队列(event queue)中。比如执行了setTimeout(callback1, 1000),会创建一个计时器,并且在另一个线程(浏览器定时触发线程)里面监听计时器是否过期,等到计时器过期后,会将对应回调 callback1加入事件回调队列中。

第三步:等到第一步中的微任务执行完毕之后,会判断事件回调队列(event queue)是否为空。如果不为空,则会取出并执行最先进入队列的回调函数,执行过程如同第一步。如果为空,则会视情况进行等待或挂起主线程。

补充说明:浏览器的内核是多线程的,常驻线程有浏览器 GUI 渲染线程、JavaScript 引擎线程、浏览器定时触发器线程、浏览器事件触发线程、浏览器 http 异步请求线程。

2.宏任务与微任务

宏任务(macrotask):script(整体代码)、setTimeout/setInterval、I/O、UI rendering等

微任务(microtask):Promise、MutationObserver等

JS代码执行过程——宏任务与微任务的执行示意图:

如图,可以看出JS执行过程中,是先执行一个宏任务,再执行这个宏任务产生的对应微任务,执行完毕后,再执行后面的宏任务,以此往复。

3.实例分析

使用浏览器:Chrome Version 80.0.3987.163

第一组:

比较 setTimeout 与 Promise

console.log('start')

setTimeout(() => {
console.log('setTimeout')
}, 0); Promise.resolve().then(() => {
console.log('microtask: promise')
}) console.log('end')

结果:

分析:

以JS的事件循环机制来分析。首先,script(整体代码)算是一个宏任务,执行完毕,会先后输出"start"和"end",然后执行这个过程中产生的微任务,即promis.then中的回调,输出"microtask: promise";这个过程中也调用了 Web API 中的 setTimeout,会创建一个计时器,过期后将回调添加到事件回调队列中;然后再执行回调(第二个宏任务),输出"setTimeout"。与浏览器运行输出一致,符合预期。

第二组:

宏任务与微任务的执行顺序对比

function func1() {
console.log('func1')
Promise.resolve().then(() => {
console.log('microtask.promise1')
})
} function func2() {
console.log('func2')
Promise.resolve().then(() => {
console.log('microtask.promise2')
})
} function main() {
func1()
func2()
setTimeout(func1, 0);
setTimeout(func2, 0);
} main()

结果:

分析:

从输出结果可以看出,当一个宏任务执行完毕后,会接着执行相应的所有微任务,执行完毕后,再执行后续的宏任务,并以往复,与预期相符。

4.参考

并发模型与事件循环

Javascript event loop

JavaScript Event Loop Explained

HTML系列:macrotask和microtask

【翻译】Promises/A+规范

浏览器中 JS 的事件循环机制的更多相关文章

  1. 浏览器中的JavaScript事件循环机制

    浏览器的事件循环机制是HTML中定义的规范. JavaScript有一个主线程和调用栈,所有的任务都会被放到调用栈等待主线程执行. JS调用栈 是一种先进后出的数据结构.当函数被调用时,会被添加到栈中 ...

  2. JS JavaScript事件循环机制

    区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...

  3. Node.js 的事件循环机制

    目录 微任务 事件循环机制 setImmediate.setTimeout/setInterval 和 process.nextTick 执行时机对比 实例分析 参考 1.微任务 在谈论Node的事件 ...

  4. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

  5. JS:事件循环机制、调用栈以及任务队列

    点击查看原文 写在前面 js里的事件循环机制十分有趣.从很多面试题也可以看出来,考察简单的setTimeout也就是考察这个机制的. 在之前,我只是简单地认为由于函数执行很快,setTimeout执行 ...

  6. js的事件循环机制和任务队列

    上篇讲异步的时候,提到了同步队列和异步队列的说法,其实只是一种形象的称呼,分别代表主线程中的任务和任务队列中的任务,那么此篇我们就来详细探讨这两者. 一.来张图感受一下 如果看完觉得一脸懵逼,请继续往 ...

  7. JS基础-事件循环机制

    从一道题浅说 JavaScript 的事件循环 原文链接: https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7 ...

  8. js事件循环机制辨析

     对于新接触js语言的人来说,最令人困惑的大概就是事件循环机制了.最开始这也困惑了我好久,花了我几个月时间通过书本,打代码,查阅资料不停地渐进地理解他.接下来我想要和大家分享一下,虽然可能有些许错误的 ...

  9. JS 事件循环机制 - 任务队列、web API、JS主线程的相互协同

    一.JS单线程.异步.同步概念 从上一篇说明vue nextTick的文章中,多次出现“事件循环”这个名词,简单说明了事件循环的步骤,以便理解nextTick的运行时机,这篇文章将更为详细的分析下事件 ...

随机推荐

  1. Java中Comparable和Comparator的区别

    前言 最近复习遇到了这个问题,在此进行一个详细的记录,分享给大家. 两个接口的区别 包区别 Comparable接口是在java.lang下. Comparator接口是在java.util下. 使用 ...

  2. 【C++】Strassen算法代码

    本文仅代码,无理论解释 实话实说,我觉得这个算法在C系列的语言下,简直垃圾到爆炸--毕竟是一群完全不懂程序数学家对着纸弄出来的,看起来好像非常的有用,实际上耗时是非常爆炸的. 但是<算法导论&g ...

  3. Codeforces Round #567 (Div. 2) B. Split a Number

    Split a Number time limit per test 2 seconds memory limit per test 512 megabytes input standard inpu ...

  4. vue采坑记录

    1.项目在浏览器运行的时候没有ico图标 <link rel="shortcut icon" type="image/x-icon" href=" ...

  5. Java 访问修饰符大全详解

    鉴于笔试面试总会遇到,决心仔细认真梳理一下: 1:涉及的关键字:public,default(表示缺省),protected,private,static,final,abstract. 2:关键字含 ...

  6. 两个看似相同,结果不同的SQL逻辑

    一朋友问我的,看着挺有意思,记录一下: 表item1,里面有上面三个字段,一共10条数据,接下来有两个相似的sql语句得到了不一样的查询结果. 表数据如下:  两条SQL及查询结果: 我的理解答: S ...

  7. coding++:MD5加密(JAVA加密 与 JS加密不一致问题)

    要求:根据指定 字符加密   JS中的加密方法 要和 JAVA中的算法保持一致,解决如下: var rotateLeft = function (lValue, iShiftBits) { retur ...

  8. 高性能RabbitMQ

    1,什么是RabbitMq RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件).RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开 ...

  9. SimpleITK 和 Nibabel 读取医学图像 nii 数据(2D显示)

    SimpleITK 和 Nibabel 区别在于:(nii图像可以看成2维,也可以看成三维) SimpleITK读取数据是(X,Y,Z)显示,Nibabel读取图像是(Z,Y,X)显示,也就是Niba ...

  10. 火焰图--记一次cpu降温过程

    引子 正值周末,娃儿6:30又如闹铃般准时来叫醒了我们.年前离开美菜,又回到了杭州.原本是想有更多时间陪伴娃儿,然而新的工作节奏与工作地点,让我们每天都是早上见面:这不,为了周末可以多玩一会儿,早早就 ...