js【深度解析】代码的执行顺序

代码的分类

我们将每一句要执行的 js 代码当做一个任务,则 js 代码可以按照其执行方式的不同,按下图分类

在这里插入图片描述

  • 同步任务:立即执行的代码
  • 异步任务:延迟执行的代码
    • 微任务:被放入微任务队列(micro task queue)中等待执行的代码

      因为Promise、async 、await 都是 ES6 语法定义的

    • 宏任务:被放入 Web APIs 中等待执行的代码

      因为 setTimeout 、setInterval、ajax、Dom事件都是浏览器定义的

不同类型代码执行的顺序和过程

1. 同步任务

  1. 将其放入调用栈(Call Stack)中
  2. 执行该段代码
  3. 将其从调用栈中移除

除 Promise、async 、await、setTimeout 、setIntervall、ajax、Dom事件之外的代码都是可立即执行的同步任务

2. 微任务

  1. 将其放入微任务队列中等待执行

  2. 待所有同步任务执行完毕,开始按微任务队列依次执行微任务

    将第1个进入微任务队列的微任务放入调用栈中,执行微任务内的代码,将其从调用栈中移除,再将第2个进入微任务队列的微任务放入调用栈中,执行,移除…… 以此类推,直到清空微任务队列。

3. DOM 渲染

微任务队列清空后,便暂停 js 代码的执行,开始尝试渲染 DOM, 若没有 DOM操作,则跳过此步。

因 JS 可修改 DOM 结构 , 所以 js 代码的执行和 DOM 渲染必须共用一个线程,这便导致 js 代码的执行和 DOM 渲染无法同时进行。

4. Event Loop 事件轮询

DOM渲染完毕后,便触发Event Loop,开始事件轮询

5. 宏任务

  1. 将其放入 Web APIs 中,并开始计时

  2. 计时结束后,将其放入回调队列(Callback Queue)

  3. 回调队列中的宏任务,依次被事件轮询到

    将第1个进入回调队列的宏任务放入调用栈中,执行宏任务内的代码,将其从调用栈中移除,再将第2个进入回调队列的宏任务放入调用栈中,执行,移除…… 依此类推,直到清空回调队列。

最终 js 代码的执行顺序

因不同类型的代码可能层层嵌套,所以最终 js 代码的执行顺序可能非常复杂,但总的运行方式,如上文所言,根据代码的不同,将其放入不同的队列或栈中,然后依次执行,核心要领在于

  1. 依次执行可执行的同步任务,直到清空调用栈
  2. 依次执行微任务队列中的微任务,直到清空微任务队列
  3. 暂停 js 代码的执行,尝试渲染DOM,若无DOM操作,则直接进入第4步,若有DOM操作,则待DOM渲染完成,进入第4步
  4. 开始事件轮询,依次执行回调队列中的宏任务(事件轮询会一直进行下去,一旦有新的宏任务计时结束进入回调队列,就会被送去调用栈执行)

简单概括如下图所示:

在这里插入图片描述

自测题

console.log(100)

// 宏任务
setTimeout(() => {
    console.log(200)
})

// 微任务
Promise.resolve().then(() => {
    console.log(300)
})

console.log(400)

答案 100 400 300 200

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}

async function async2() {
  console.log("async2");
}

console.log("script start");

setTimeout(function () {
  console.log("setTimeout");
}, 0);

async1();

new Promise(function (resolve) {
  console.log("promise1");
  resolve();
}).then(function () {
  console.log("promise2");
});

console.log("script end");

答案

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

解析:详见代码注释

// 定义函数,先跳过
async function async1() {
  console.log("async1 start"); // 2
  await async2(); // 先执行 async2() , 进入 async2 函数内

  // await 后的代码都是微任务,将其放入微任务队列 --- 微任务 1
  console.log("async1 end"); // 6
}

// 定义函数,先跳过
async function async2() {
  console.log("async2"); // 3
}

// 同步任务
console.log("script start"); // 1

// 宏任务 1
setTimeout(function () {
  console.log("setTimeout"); // 8
}, 0);

// 同步任务
async1(); // 进入 async1 函数内

// 同步任务 -- Promise 函数体内的代码会立刻执行
new Promise(function (resolve) {
  console.log("promise1"); // 4
  resolve(); // Promise 状态变为 resolved , 立即触发了 then 函数
}).then(function () {
  // then 函数是个微任务,将其放入微任务队列 --- 微任务 2
  console.log("promise2"); // 7
});

// 同步任务
console.log("script end"); // 5

// 同步任务执行完毕,开始执行微任务
// 依次执行微任务1 和 微任务 2
// 最后执行宏任务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/443946.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【记录37】VueBaiduMap 踩坑一

截图 错误 Error in callback for watcher “position.lng”: “TypeError: Cannot read properties of undefined (reading ‘setPosition’)” 解释 回调观察程序“content”时出错:“TypeError:无法读取未定义的属性(读取’setContent’)”…

设计模式-行为型模式-模版方法模式

模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。[DP] 模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。 //首…

L-2:插松枝(Python)

作者 陈越 单位 浙江大学 人造松枝加工场的工人需要将各种尺寸的塑料松针插到松枝干上,做成大大小小的松枝。他们的工作流程(并不)是这样的: 每人手边有一只小盒子,初始状态为空。每人面前有用不完的松枝干和一个推送…

《汇编语言》第3版(王爽)实验9

第9章 实验9 编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串 ‘welcome to masm!’ assume cs:code,ds:datadata segmentdb welcome to masm!,0 data endscode segmentstart:mov ax,data mov ds,ax ;ds指向data段mov ax,0B800H ;显存空间从B800H…

LeetCode_24_中等_两两交换链表中的节点

文章目录 1. 题目2. 思路及代码实现(Python)2.1 递归2.2 迭代 1. 题目 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换…

windows11编译FFmpeg源码完整步骤

1.安装MSYS2 下载并安装MSYS2 安装GCC GCC安装成功 克隆FFmpeg源码 打开MSYS2终端并进入ffmpeg文件夹,然后输入./configure回车开始生成makefile

JavaEE——简单认识JS(Web API)

文章目录 一、认识什么是 WebAPI二、认识事件三、操作元素1. innerHTML 属性2. 获取 / 修改元素内容3. 获取 / 修改 元素属性4. 获取 / 修改 表单元素属性5. 获取 / 修改 样式属性6. 创建 / 删除元素 一、认识什么是 WebAPI 1.什么是API 在我们了解 WebAPI 之前,我们…

苍穹外卖学习-----2024/03/09

1.菜品分页查询 代码在这里 分页查询菜品 2.删除菜品 [链接]param 1、概览 本文将带你了解 Spring 中 RequestParam 注解的用法。 简单地说,可以使用 RequestParam 从请求中提取查询参数、表单参数甚至是多个参数。 2、示例端点 假设我们有一个端点 /api/foos&a…

二叉树遍历(前中后序的递归/非递归遍历、层序遍历)

二叉树的遍历 1. 二叉树的前序、中序、后序遍历 前、中、后序遍历又叫深度优先遍历 注:严格来说,深度优先遍历是先访问当前节点再继续递归访问,因此,只有前序遍历是严格意义上的深度优先遍历 首先需要知道下面几点: …

Spring学习 基础(三)MVC

5、Spring MVC 传统Web模式: Model:系统涉及的数据,也就是 dao 和 bean。View:展示模型中的数据,只是用来展示。Controller:处理用户请求都发送给 ,返回数据给 JSP 并展示给用户。 随着 Spring 轻量级开发…

Vue项目实战-空间论坛(2)

项目实战 实现userlist页面 获取userlist列表,可使用ajax,axios 实现 这里采用ajax实现,需要添加Jquery依赖,然后在UserListView.vue中引入 在UserListView.vue组件的入口函数中定义users变量,并引入ref 使用ajax从云端动…

目标检测——监控下打架检测数据集

一、简述 首先,监控下打架检测是维护公共安全的重要手段。在公共场所、学校、监狱等地方,打架事件往往难以避免。通过安装打架检测监控系统,可以实时监控并准确识别打架事件,及时采取必要的应对措施,有效地减少打架事…

手写分布式配置中心(五)整合springboot(不自动刷新的)

springboot中使用配置方式有四种,分别是environment、BeanDefinition、Value、ConfigurationProperties。具体的原理可以看我之前的一篇文章https://blog.csdn.net/cjc000/article/details/132800290。代码在https://gitee.com/summer-cat001/config-center 原理 …

PTA L2-004 这是二叉搜索树吗?

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点, 其左子树中所有结点的键值小于该结点的键值;其右子树中所有结点的键值大于等于该结点的键值;其左右子树都是二叉搜索树。 所谓二叉搜索树的“镜像”&#xf…

减少PDF文件大小的方法,亲测巨好用!!!

周六晚上,导师突然发了两个pdf,让把大小改成1M以下!!! 试了很多方法最后,发现了个最好使用的,不过需要下载下Adobe Acrobat文件编辑软件,下载地址如下 链接:https://pan.…

基于Java的开放实验室管理系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实验管理模块2.4 实验设备模块2.5 实验订单模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示五、样例代码5.1 查询实验室设备5.2 实验放号5.3 实验预定 六、免责说明 一、摘…

LVS+Keepalived 高可用集群

一、Keepalived工具介绍 支持故障自动切换(Failover) 支持节点健康状态检查(Health Checking) 基于vrrp协议完成地址流动 为vip地址所在的节点生成ipvs规则(在配置文件中预先定义) 为ipvs集群的各RS做健康状态检测 基于脚本调用接口完成脚本中定义的功能,进而…

链表|19.删除链表的倒数第N个节点

力扣题目链接 struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {//定义虚拟头节点dummy 并初始化使其指向headstruct ListNode* dummy malloc(sizeof(struct ListNode));dummy->val 0;dummy->next head;//定义 fast slow 双指针struct ListNode* f…

springboot整合shiro的实战教程(一)

文章目录 1.权限的管理1.1 什么是权限管理1.2 什么是身份认证1.3 什么是授权 2.什么是shiro3.shiro的核心架构3.1 Subject3.2 SecurityManager3.3 Authenticator3.4 Authorizer3.5 Realm3.6 SessionManager3.7 SessionDAO3.8 CacheManager3.9 Cryptography 4. shiro中的认证4.1…

Cocos Creator 2d光照

godot游戏引擎是有2d光照的,用起来感觉还是很强大的,不知道他是怎么搞的,有时间看看他们怎么实现的。 之前一直以为cocos社区里面没有2d光照的实现,偶然看到2d实现的具体逻辑,现在整理如下, 一&#xff1…