js是如何单线程执行的

2023-10-29

据大家所知,js都是单线程执行的。那么就会接触到线程与进程,同步执行与异步执行,以及js单线程执行原理概念。

一、进程与线程的概念

1.1 进程

进程是CPU进行资源分配的基本单位,浏览器使用的是多进程,一个标签对应一个进程,此进程负责管理各个标签的创建与销毁,前进后退等操作。

1.2 线程

线程是CPU调度最小单位,多个线程可以对应到单一进程,而且可以它们可以共享进程的内存大小。

二、js单线程是如何实现同步与异步

2.1 js为什么是单线程

若js是多线程的话,同时执行会有线程冲突。
例如第一线程在DOM的node节点A对他进行新增内容,第二个线程则对此A节点进行了删除操作,那么最终是以哪个进程为主?
所以js是采用单线程,一次仅仅会执行一件同步任务。但不代表js引擎中只有一个线程,只是代表只有一个线程(通常称为主线程)是用来执行js代码,其它线程则是处理后台配合。

2.2 js执行同步任务

2.2.1 js执行同步任务的原理

js是单线程也就是说同时只能执行一个任务,而其它剩下的任务需要在后面等待。当前面的任务执行完了,才执行后面的任务。

2.2.2 js执行同步任务与栈的关系

js在执行同步任务时,所选用的数据结构是栈,保持先进后出,有序的概念。
例如执行一个任务函数A会调用函数B,那么函数B的栈帧变成当前帧,而函数A的栈帧会变成调用帧。当函数B执行完才回调到函数A继续把A执行完。

2.3 js执行异步任务

2.3.1 js执行异步任务的原理

当JS碰到异步执行的任务时,会先把它放到任务队列中,暂不处理此异步任务,而是继续往下执行同步任务,这样不会进行使JS单线程任务阻塞。
当js单线程空闲下来以及任务队列中的异步任务通知可以执行了,才会把此异步任务从任务队列中取出来,放到线程上执行。

2.3.2 什么是任务队列

任务队列是用来存放js单线程所遇到的异步任务。任务队列有多个。

2.3.3 js执行异步任务与队列的关系

我们知道任务队列是以队列的数据结构,保持先进先出,有序的概念。
也就是说,当js单线程的执行栈空了,就会从任务队列按顺序取出来依次执行(要是任务队列都通知队列中异步任务都能执行的情况下)

2.3.4 任务队列是如何运用

进行回调函数的形式通知执行栈可以执行。
基本以下情况会通过Web APIs按照一定的规则,再对上面的任务进行划分宏事件放入宏队列中,微事件放如微队列中(此概念会在2.3.5进行叙述),例如:

  1. DOM Binding模块处理一些onclick的函数
  2. network模块处理ajax请求
  3. 使用计时器setTimeout
  4. 使用promise

为了能够实时检查到任务队列中是否能够回调用到主线程中运行,使用的是事件循环Event Loop。
就是创建一个类似while(true)的循环过程,循环过程成为Tick。JS的单线程不停的一遍一遍循环,查看任务队列中是否有异步任务要执行,如果有则取出该相关事件,并通过回调函数放入单线程的执行栈中。

2.3.5 任务队列的宏任务,微任务

2.3.5.1 什么是宏任务,微任务

  • 宏任务:js中全局的同步代码,setTimeout管理模块,AJAX请求管理模块,Dom事件管理模块等
  • 微任务:Promise管理模块,mutation管理模块

2.3.5.2 宏任务与微任务的执行原理

在同步任务都执行完,执行栈为空的基础下(同步任务相当于第一个宏任务执行完),每当宏任务执行完之后,会先查看是否微队列中有任务。有则全部执行完再执行第二个宏任务;没有则直接执行第二个宏任务。以此类推。

2.3.5.3 宏任务与微任务的执行代码理解以及动图

console.log('start')
setTimeout(function() {
  console.log('setTimeout')
}, 0)

Promise.resolve().then(function() {
  console.log('promise1')
}).then(function() {
  console.log('promise2')
})

console.log('end')

具体代码执行栈以及对应任务队列操作如下:
在这里插入图片描述

在上述代码以及动图中可以看出,从上往下顺序执行。
我们先分成同步任务与异步任务两部分:
一、同步执行
1.遇到console.log(‘start’)属于同步任务,直接执行。
2.遇到setTimeout代码块属于异步任务中的宏任务,把它放入任务队列中的宏队列macrotask挂起。
3.遇到Promise代码块属于异步任务中的微任务,把它放入任务队列中的微队列microtask中挂起。
4.遇到console.log(‘end’)属于同步任务,直接执行,至此同步任务已全部执行完成。

二、异步执行
1.同步任务完成之后,全局代码属于macrotask宏任务,此宏任务执行完之后就开始检查任务队列中的微队列是否有执行。
2.把微任务的Promise代码块回调,放入执行栈中执行,执行其中的console.log(‘promise1’)。
3.微任务的Promise代码块回调函数返回undefined。接着,primose的状态会从pending转换成fulfilled,继续放入microtask微队列之中。
4.进入event loop事件循环,此时执行.then()回调执行console.log(‘promise2’),至此异步任务的微任务队列完成。
5.再次进入event loop事件循环,就执行异步任务中的宏任务(此时微任务已没有需要执行,所以直接执行下一个宏任务)。执行setTimeout(),延时0之后,console.log(‘setTimeout’)。
6.至此任务队列全部执行完成,event loop还在循环等待新一轮需要处理的代码。

2.3.6 异步任务中的async-await

线程的执行顺序同时还会牵扯到async-await,promise,setTimeOut影响。现在主要重点关注async-await。

2.3.6.1 async-await是什么?

async是个函数且返回一个Promise对象,和await搭配使用。当在async函数中碰到await时,await就像是让出线程的操作,右边内容完成时让出线程,并把async剩下的代码挂起,等待剩下同步任务完成后才执行。

2.3.6.1 async-await,promise,setTimeOut的代码运行

	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

可以看出function async2()返回是一个Promise,await async2()相当function async2()的,then()执行成功返回会的值。此时awiat会让出线程,跳出function async1()的异步执行,继续执行下面的同步任务,等同步任务全部执行完毕,再执行function async1()剩下的部分。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js是如何单线程执行的 的相关文章

  • 我如何能够以两行显示标题,并且每行的字体大小不同?

    我正在使用 Google Chart API 创建时间线图 并希望将图的标题修改为两行 问题 我如何能够显示具有不同字体大小的两线图表标题 电流输出 理想输出 相关研究 我唯一能找到的是有人试图用饼图来做到这一点 但我尝试了但无法使其发挥作
  • 由于 apollo-client 未定义,无法解构 GraphQL 查询?

    我正在寻找调试与错误消息相关的问题 未捕获的类型错误 无法解构 0 apollo client WEBPACK IMPORTED MODULE 4 useQuery 因为它未定义 Context 我正在为我的 React js 项目设置后端
  • 渲染货币和符号并与来自不同单元格的数据相结合

    我正在使用最新的 jQuery DataTables v1 10 7 我正在尝试将数字解析为以下格式 239 90 USD 我可以使用此命令使货币正常工作 columns data Price render fn dataTable ren
  • socket.io 的良好初学者教程? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Javascript Promise“then”始终运行,即使 Promise 未能执行

    我希望当调用第二个 then 时不执行第三个 then 但是 即使 Promise 被拒绝 调用第二个 then 并且代码返回 rejected 然后返回 undefined 它仍然调用第三个 then 如何不运行第三个 then 这样 未
  • 以编程方式填写reactjs表单

    我正在编写一个用户脚本 但无法填写由reactjs制作的表单 我的代码 document querySelector id username value email protected cdn cgi l email protection
  • Three.js:缩放几何图形后错误的 BoundingBox

    在我的场景中 我有一个简单的立方体 var test new THREE Mesh new THREE CubeGeometry 10 10 10 new THREE MeshBasicMaterial scene add test 该立方
  • 如何针对 Node.js 中发生的每个错误发送电子邮件?

    假设我的 node js 应用程序正在运行 如果出现错误 我的意思是所有错误 不仅仅是网络错误 如果出现错误 则很重要 我如何调用函数向我发送电子邮件 基本上 在我希望它写入 err out 之前 我希望向我发送一封电子邮件 我正在使用no
  • 如何纠正流警告:解构(缺少注释)

    我正在编写一个小型 React Native 应用程序 并且正在尝试使用 Flow 但我无法在任何地方真正获得有关它的正确教程 我不断收到错误 destructuring Missing annotation 有关 station 这段代码
  • Javascript split 不是一个函数

    嘿朋友们 我正在使用 javascript sdk 通过 jQuery facebook 多朋友选择器在用户朋友墙上发布信息 但是我收到此错误friendId split 不是函数 这是我的代码 function recommendToFr
  • 将 UMD Javascript 模块导入浏览器

    你好 我正在对 RxJS 进行一些研究 我可以通过在浏览器中引用它来使用该库 如下所示 它使用全局对象命名空间变量 Rx 导入 我可以制作可观察的东西并做所有有趣的事情 当我将 src 更改为指向最新的 UMD 文件时 一切都会崩溃 如下所
  • 页面上使用 HTML Editor Extender 进行回发会导致 IE11 中出现 JavaScript 错误

    我已将 HTML 编辑器扩展程序添加到我正在处理的页面中 现在每当我在页面上发回帖子时 都会收到以下 Javascript 错误 JavaScript 运行时错误 参数无效 之后什么也没有发生 这在 IE10 或更低版本以及我所知道的所有其
  • 可以设置标题样式吗? (并且使用CSS或js?)[重复]

    这个问题在这里已经有答案了 我想知道是否可以设计一个title a href title This is a title Hello a 样式问题有两个方面 文本格式 编码 我猜这是可能的 所以在问题中这样做 工具提示样式 你能把它弄大一点
  • Javascript 假值(null、未定义、false、空字符串:“”或 '' 和 0)和比较(==)运算符 [重复]

    这个问题在这里已经有答案了 当我使用任何一个值时 null undefined false 0 in a if陈述 它总是被评估为谬误 false 另外 这些值的否定 null undefined false 0 in a if语句总是被评
  • 从数据库检查数据的异步解决方案各种循环子句

    我想要做的是异步检查数据库并从中获取结果 在我的应用程序中我试图实现Asynchronously将此步骤解决为 从数据库中检查手机号码JsonArray循环子句的种类 Create JsonArray从结果 打印创建的数组 我学到了足够多的
  • Three.js 各种大小的粒子

    我是 Three js 的新手 正在尝试找出添加 1000 个粒子的最佳方法 每个粒子都有不同的大小和颜色 每个粒子的纹理是通过绘制画布创建的 通过使用粒子系统 所有粒子都具有相同的颜色和大小 为每个粒子创建一个粒子系统是非常低效的 有没有
  • 使用 Vue 的多模式组件

    我在 Vue 中实现动态模式组件时遇到问题 A common approach I follow to display a set of data fetched from the db is I dump each of the rows
  • Vue 和 Vuex:处理依赖的计算属性

    我的应用程序是一个使用 Vuex 在 Vue 中构建的精简电子表格 关键组件是TableCollection Table and Row The TableCollection有一个包含多个的数组Table对象 每个Table有一个包含多个
  • 在 Shopify 商店中嵌入 Vue 组件

    在产品页面中 我尝试显示自定义 Vue 组件 为简洁起见 该组件根据给定的产品 ID 显示 Firebase 数据库中的一些信息 我最初尝试将其制作为 Shopify 应用程序 以便我可以访问他们的 API 我实现了 OAuth 并且可以检
  • 如何用另一个响应替换窗口的 URL 哈希?

    我正在尝试使用替换方法更改哈希 URL document location hash 但它不起作用 function var anchor document location hash this returns me a string va

随机推荐

  • suse11/12下关闭防火墙

    service SuSEfirewall2 init stop chkconfig SuSEfirewall2 init off 启动操作为 service SuSEfirewall2 setup start service SuSEfir
  • 通过java解析域名获得IP地址

    IP地址是Internet主机的作为路由寻址用的数字型标识 人不容易记忆 因而产生了域名 domain name 这一种字符型标识 DNS即为域名解析服务 在这里我们如果想通过java程序来解析域名获得真实IP的话 可以通过java的Ine
  • C语言指针高级篇

    相信很多人都听过指针是c语言的灵魂 对于指针的学习 往往也是最难的 也是最难搞懂的 那么今天我们一起来学习分析c语言的指针 体会c语言的魅力 指针和指针应用大概分为一下几类 1 字符指针 2 数组指针 3 指针数组 4 数组传参和指针传参
  • Node.js笔记-day04

    18 Node js 回调函数 Node js 异步编程的直接体现就是回调 异步编程依托于回调来实现 但不能说使用了回调后程序就异步化了 回调函数在完成任务后就会被调用 Node 使用了大量的回调函数 Node 所有 API 都支持回调函数
  • Linux关于文件或者目录的常见命令

    1 查看当前所在目录 print working directory 该命令的基本格式为 root localhost pwd 2 查看指定目录下所有的子目录或者文件列表 list 该命令的基本格式为 root localhost ls 选
  • Axios(万字详细教程)

    Axios介绍 1 Axios是什么 Axios是一个基于promise的HTTP库 类似于jQuery的ajax 用于http请求 可以应用于浏览器端和node js 既可以用于客户端 也可以用于node js编写的服务端 2 Axios
  • idea项目无法打包

    打包过程 点击maven 点击lifecycle后点击package 运行后出现 打包出错 原因是plugins标签里面缺少maven resources plugin依赖 需要在pom xml里面添加依赖
  • Zimg—轻量级图片服务器搭建利器

    在一个互联网应用中 图片扮演着越来越重要的角色 有稳定的可扩展的图片存储服务器就显得尤为的重要 云厂商们提供了便利的图片存储服务 花钱就可以解决了 这里简单介绍一个开源的一个分布式图片存储服务器 zimg 来自己搭建一个图片服务器 当然你也
  • 2022阿里巴巴全球数学竞赛 第4题 虎虎生威(盲盒问题、集卡问题)解决思路

    目录 题目 基础概念 数学期望 题解 虎生威 问题 水浒传108卡 问题 虎虎生威 问题 题目 来自 2022阿里巴巴全球数学竞赛 第4题 单选题 基础概念 数学期望 在概率论和统计学中 数学期望 mathematic expectatio
  • 机器学习好伙伴之scikit-learn的使用——特征提取

    机器学习好伙伴之scikit learn的使用 特征提取 什么是特征提取 sklearn中特征提取的实现 PCA 主成分分析 LDA 线性评价分析 应用示例 PCA部分 LDA部分 有些时候特征太多了 可以利用sklearn中自带的函数进行
  • Yii Framework 开发教程(48) 多国语言示例

    本例通过Yii Framework 开发教程 11 UI 组件 ActiveForm示例添加中文支持简要说明一下多国语言支持 详细文档可可以参考Yii文档 信息翻译是通过调用 Yii t 实现的 此方法会将信息从 源语言 翻译为 目标语言
  • DVWA学习之XSS(跨站脚本攻击)(超级详细)

    DVWA学习之XSS XSS 跨站脚本攻击 0x01 XSS Cross Site Script 简介 0x02 何为XSS 0x03 XSS存在的原因 0x04 XSS漏洞的危害 0x05 XSS 的分类及特点 1 存储型XSS 2 反射
  • 初识C语言(3)

    目录 8 函数 函数的特点就是简化代码 代码复用 9 数组 要存储 1 10 的数字 怎么存储 C 语言中给了数组的定义 一组相同类型元素的集合 9 1数组的定义 9 2数组的下标 C 语言规定 数组的每个元素都有一个下标 下标是从 0 开
  • 人工智能——机器学习,数据特征预处理,数据降维

    数据特征预处理 数据降维 处理方法 1 数值型数据 标准缩放 1 归一化 2 标准化 3 缺失值 2 类别型数据 one hot 编码 3 时间类型 时间的切分 下面是归一
  • Git --- 基础介绍

    Git 基础介绍 git 是什么 git 工作区 暂存区 资源库 git 文件状态 git branch 和 HEAD git 一次正常的git提交流程 git 是什么 Git是一款分布式源代码管理工具 版本控制工具 Git和其他传统版本控
  • HTTP 与 HTTPS 的区别

    HTTP 与 HTTPS 的区别 文章目录 HTTP 与 HTTPS 的区别 前言 一 基本概念 二 HTTP 与 HTTPS 区别 三 TCP 三次握手 四 HTTPS 的工作原理 我的公众号 前言 一 基本概念 HTTP HyperTe
  • 基于SSM+Vue游戏商城系统Java游戏攻略网站(源码调试+讲解+文档)

    作者 计算机源码社 个人简介 本人七年开发经验 擅长Java 微信小程序 Python Android等 大家有这一块的问题可以一起交流 学习资料 程序开发 技术解答 代码讲解 文档报告 JavaWeb项目 微信小程序项目 Python项目
  • Servlet(GenericServlet相关)

    Servlet是用于实现web浏览器和java程序的对应关系 通过浏览器请求服务器调用对应的java程序 就是Servlet的主要功能 一个使用Servlet的类必须实现Servlet接口 implements Servlet 并且实现其中
  • 服务器巡检规范

    服务器巡检规范 01 服务器主机巡检规范 02 服务器日常巡检细则 03 管理员账号管理规范 04 用户服务器系统使用规范 05 机房来访人员管理规范 06 主机防火墙管理规范 07 组织容器命名规范 08 服务器主机名命名规范 01 服务
  • js是如何单线程执行的

    据大家所知 js都是单线程执行的 那么就会接触到线程与进程 同步执行与异步执行 以及js单线程执行原理概念 一 进程与线程的概念 1 1 进程 进程是CPU进行资源分配的基本单位 浏览器使用的是多进程 一个标签对应一个进程 此进程负责管理各