Javascirp异步编程

2023-10-31

在上一篇彻底弄清Javascirpt中的同步和异步一问当中,介绍了Javascirp代码执行的概念,同步和异步的原理。

学习过Javascript语言的同学都知道,从Javascript诞生之日起,就是一门单线程、非阻塞的脚本语言。Javascript代码在执行的时候,都有一个主线程来处理所有任务,非阻塞就是靠异步编程,即事件循环(Event loop)。

本文将向大家讲述,在js当中如何实现异步编程的。

在本文之前先了解一下队列的概念

队列 (queue)

队列的特点是是"FIFO,即先进先出(First in, first out)" 。
数据存取时"从队尾插入,从队头取出"

"与栈的区别:栈的存入取出都在顶部一个出入口,而队列分两个,一个出口,一个入口"

JS为何需要异步?

for (var i=0;i<9999;i++){
  console.log("我在执行 但用户不知道")
}
console.log("你好啊")

上图例子 for循环耗时会很久

这意味着 用户得不到 '你好啊' 的响应 就会下意识会认为浏览器卡死了 所以js必须要有异步。

JS事件的循环

js通过事件循环来实现异步 这也是js的运行机制

image

调用栈中的同步任务都执行完毕,栈内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环。 

 

导图要表达的内容用文字来表述的话:

  • 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
  • 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
  • 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
  • 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

通常把异步任务分为宏任务与微任务,它们的区分在于:

  • macro-task(宏任务)包括整体代码 script,setTimeout,setInterval,setImmediate(node.js, MessageChannel postMessage  requestAnimationFrame I/O操作 UI渲染。

        一般是 JS 引擎和宿主环境发生通信产生的回调任务,比如 setTimeout,setInterval 是浏览器进行计时的,其中回调函数的执行时间需要浏览器通知到 JS 引擎,网络模块, I/O处理的通信回调也是。包含有 setTimeout,setInterval,DOM事件回调,ajax请求结束后的回调,整体 script 代码,setImmediate。

  • 微任务(micro-task):一般是宏任务在线程中执行时产生的回调,如 Promise,process.nextTick,Object.observe(已废弃), MutationObserver(DOM监听),这些都是 JS 引擎自身可以监听到回调。

上面我们了解了宏任务与微任务的分类,那么为什么我们要将其分为宏任务与微任务呢?主要是因为其添加到事件循环中的任务队列的机制不同。

在事件循环中,任务一般都是由宏任务开始执行的(JS代码的加载执行),在宏任务的执行过程中,可能会产生新的宏任务和微任务,这时候宏任务(如ajax回调)会被添加到任务队列的末尾等待事件循环机制执行,而微任务则会被添加到当前任务队列的前端,也是等待事件循环机制的执行。

其中相同类型的宏任务或微任务会按照回调的先后顺序进行排序,而不同任务类型的任务会有一定的优先级,按照不同类型任务区分

总计起来就是,Javascript在代码的执行过程中,先同步再异步,在异步执行时,先微任务再宏任务。

整体任务的顺序: 先进行宏任务(可以有多个)-> 微任务 -> 宏任务 -> 微任务 ···

 这个例子看懂基本js执行机制就理解了

console.log(1);
setTimeout(function() {
    console.log(2);
})
var promise = new Promise(function(resolve, reject) {
    console.log(3);
    resolve();
})
promise.then(function() {
    console.log(4);
})
console.log(5);

示例中,setTimeout 和 Promise被称为任务源,来自不同的任务源注册的回调函数会被放入到不同的任务队列中。

有了宏任务和微任务的概念后,那 JS 的执行顺序是怎样的?是宏任务先还是微任务先?

第一次事件循环中,JavaScript 引擎会把整个 script 代码当成一个宏任务执行,执行完成之后,再检测本次循环中是否寻在微任务,存在的话就依次从微任务的任务队列中读取执行完所有的微任务,再读取宏任务的任务队列中的任务执行,再执行所有的微任务,如此循环。JS 的执行顺序就是每次事件循环中的宏任务-微任务。

  • 上面的示例中,第一次事件循环,整段代码作为宏任务进入主线程执行首先输出1,遇到Promisenew Promise直接执行,输出3,,然后是5。
  • 遇到 Promise,将 then 函数放入到微任务的微任务Event Queue中。
  • 遇到了 setTimeout ,就会等到过了指定的时间后将回调函数放入到宏任务的任务队列中。
  • 整个事件循环完成之后,会去检测微任务的任务队列中是否存在任务,存在就执行。
  • 第一次的循环结果打印为: 1,3,5,4。
  • 接着再到宏任务的任务队列中按顺序取出一个宏任务到栈中让主线程执行,那么在这次循环中的宏任务就是 setTimeout 注册的回调函数,执行完这个回调函数,发现在这次循环中并不存在微任务,就准备进行下一次事件循环。
  • 检测到宏任务队列中已经没有了要执行的任务,那么就结束事件循环。
  • 最终的结果就是 1,3,5,4,2。
 
 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascirp异步编程 的相关文章

  • Jasmine-jQuery loadFixtures 未定义

    我对整个茉莉花的事情仍然很陌生 在过去的几个小时里我陷入了这个问题 我尝试使用 loadFixture 加载外部夹具文件 我使用 Jasmine 2 0 0 和 Jasmine jQuery 2 0 5 ReferenceError loa
  • 使用 javascript 更改 div 颜色

    div style height 20px width 100 background color 000000 div br
  • 第一次使用node.js - “ReferenceError:节点未定义”

    我刚刚安装了node js 我尝试编写应该检查版本的node v 但它不起作用 这是输出 gt node v ReferenceError node is not defined at repl 1 2 at REPLServer self
  • Angular 2 Material 2 日期选择器日期格式

    我不知道如何更改材料2日期选择器的日期格式 我已阅读文档 但我不明白我实际上需要做什么 datepicker默认提供的输出日期格式为f e 6 9 2017 我想要实现的目标是将格式更改为类似的格式9 Jun 2017或任何其他 文档htt
  • html 表格单元格的条件格式

    是否有现成的解决方案可以对 HTML 表格进行条件格式设置 通过条件格式 我更感兴趣的是根据该列或其他列 在同一个表中 的值 数字 将不同的颜色作为单元格背景 类似于我们在 Excel 条件格式 gt 色阶 gt 红黄绿中的内容 我想在通过
  • 打开 md-calendar 时滚动到当前日期

    目前正在构建一个使用 Angular Material 的应用程序 我们需要一个 md calendar 组件 我们想要自定义按钮样式和内容 因此不使用普通的 md datepicker 问题是 当 md calender 打开时 滚动位置
  • 在鼠标光标位置添加 cytoscape 节点

    我想在画布上的单击事件上的鼠标箭头位置添加一个 cytoscape 节点 我怎样才能做到这一点 我的方法 效果不太好 我可以通过单击创建一个节点 但无法确保创建的节点的位置位于我单击的位置 使用这样的东西 cy click function
  • 以一定时间间隔连续重复运行 JavaScript 函数

    这是我的第一个问题 希望您尽快回答 我想要代码连续重复一个函数 我尝试了一些代码 但没有成功 我尝试了这段代码 我想在一段时间后重复这个功能 我努力了setInterval and setTimeout 但是 我还没有收到结果 这将重复该任
  • 搜索深度嵌套数组以更新对象

    我有一个深层嵌套的数据结构 我有兴趣匹配数组 和数组数组 中的某个值 然后将一些数据推送到随附的数组中 例如以下是我的数组colors并伴随着的是更多颜色数组可能存在也可能不存在 var myData color green moreCol
  • 使用 JavaScript 生成 PDF 文件

    我正在尝试将 XML 数据从网页转换为 PDF 文件 并且希望能够完全在 JavaScript 中完成此操作 我需要能够绘制文本 图像和简单的形状 我希望能够完全在浏览器中完成此操作 我刚刚写了一个名为jsPDF https github
  • jQM / jquery-collagePlus 使用问题

    我正在使用 jQM 构建应用程序 并且尝试使用 jquery collagePlus http ed lea github io jquery collagePlus http ed lea github io jquery collage
  • 如何打开弹出窗口并用父窗口中的数据填充它?

    如何使用 JavaScript jQuery 使用父页面中 JS 变量的数据填充弹出窗口 在我的示例中 我有一个文件名数组 我在父窗口中最多列出五个 如果还有更多 我想提供一个链接来打开弹出窗口并列出数组中的每个帖子 因此 如果我打开一个包
  • 如何处理requireJs超时错误?

    我正在使用 require js 作为加载框架编写一个移动混合应用程序 我遇到加载错误的问题 我想做的是在设备离线且无法下载在屏幕上显示地图所需的 google 地图 API 脚本时设置后备解决方案 我得到的只是 Uncaught Erro
  • Firebase 警告:使用 Firebase Cloud Function 搜索数据时使用未指定的索引

    我构建了一个 Firebase 云函数 用于查找 IsNotificationEnabled 值等于 true 的用户 我的部分职能 export const sendPushNotification functions https onR
  • MongoDB中如何通过引用字段进行查询?

    我有两个 Mongo 模式 User id ObjectId name String country ObjectId Reference to schema Country Country id ObjectId name String
  • 在 HTML5 iOS 7 / iOS 8 中显示十进制键盘

    经过几个小时的搜索后 我只是有一个简单的问题 是否有可能在网络浏览器输入字段中显示小数键盘 input type number 只显示数字 但我需要在左下角使用逗号或点 我尝试过任何事情 pattern step等等 但没有显示十进制键盘
  • Node npm 包抛出使用严格:全局发布和安装后未找到命令

    我正在尝试发布 npm 包 当我全局安装该包并尝试运行 cli 命令时 我收到此错误 nvm versions node v0 12 2 bin myPack line 1 use strict command not found nvm
  • Flowtype 属性“msg”缺失为 null 或未定义

    我发现 Flow 很难用 我明白那个Array find可以返回或未定义 因此 通过阅读以下内容 github Array find on Array 引发 https github com facebook flow issues 351
  • Internet Explorer 9 是否会因数组和对象文字末尾的额外逗号而卡住?

    现代浏览器和 Node js 等环境允许您说 a 1 b 2 或 1 2 3 这在历史上一直是 Internet Explorer 的问题 Internet Explorer 9 中修复了此问题吗 对此有两种不同的答案 一种是对象初始值设定
  • 从输入类型编号获取无效值

    我正在使用输入类型数字 当它无效时 我如何从中获取值 例如 使用类型编号并仅打印 e 这本身是无效的 我正在使用 React 但我认为这个问题非常普遍 onChange event console log event target valu

随机推荐

  • 《软件架构设计》一书目录

    第一部分软件架构概念与思想篇 1第1章解析软件架构概念 3 1 1软件架构概念的分类 3 1 1 1组成派 4 1 1 2决策派 5 1 2软件架构概念大观 5 1 2 1Booch Rumbaugh和Jacobson的定义 5 1 2 2
  • 机智的Open3D学习生活(第一集):入坑前的准备工作

    1 Open3D的开源项目地址 https github com isl org Open3D 2 Open3D的官网地址 http www open3d org 3 Open3D的文档地址 http www open3d org docs
  • Jetson 上cmake 带cuda 的程序报错

    报错信息为 找不到CUDA 架构 https blog csdn net qq 19449259 article details 128001426 把cuda 的nvcc 加入环境变量之后 又报了如下错误 报错信息如下 D CUDACC
  • 猿人学APP逆向第一题

    一 抓包 加密参数sign 二 静态分析 2 1搜索app1直接直接定位到请求位置 查看用例直接定位到加密位置 可以直接看到Sign sign 方法就是加密函数 2 2frida hook加密函数 一目了然 第一题太简单了就不过多分析 直接
  • JavaScript数据结构之栈

    JavaScript 数据结构之栈思维导图 JavaScript 数据结构之栈源码
  • MUI蓝牙打印(Android)

    MUI蓝牙打印 Android 使用MUI开发手机APP时使用蓝牙打印功能可能较少使用 MUI官方并为集成蓝牙打印功能 而且似乎对iPhone蓝牙打印的类库支持也不够完善 忙完一阶段后回顾下之前的工作 想想蓝牙打印功能折腾了够长时间了 写这
  • Django数据库orm操作以list形式获取数据库中某列所有值

    文章目录 问题 解决办法 方式一 方式二 方式三 写在最后 问题 如图所示 Django数据库中存储如下字段 这是在前端渲染出的数据 现在的需求是 要把factory这一列数据从后端数据库提取出来得到一个list方便后续的 select o
  • 几何画笔

    在看书时看到了这个概念 画笔可以分为几何画笔和装饰画笔 目前从CSDN以及MSDN上大致看了一下几何画笔的用法 代码如下 HPEN hPen NULL DWORD dwStyle PS GEOMETRIC PS DASHDOT PS END
  • HIT SC ADT and OOP

    ADT Abstract Data Types 在上学期的数据结构中我们已经接触过ADT 抽象数据型 抽象数据型是一个数学模型和在该模型上定义的操作的集合 在软件构造中ADT概念也类似 不过多了些值得注意的点 首先看一下MIT官网列出的几个
  • metasploit

    概念 Metasploit是一款开源的安全漏洞检测工具 可以帮助安全和IT专业人士识别安全性问题 验证漏洞的缓解措施 并管理专家驱动的安全性进行评估 提供真正的安全风险情报 这些功能包括智能开发 代码审计 Web应用程序扫描 社会工程 团队
  • 为什么重写equals还要重写hashcode

    为什么重写equals还要重写hashcode 1 简介 equals和hashcode都属于Object类的方法 其中hashcode为本地方法 object中equals是比较是否为同一对象 public boolean equals
  • Java集成微信小程序生成二维码传回前端,提供下载按钮

    1 后端调用方法获取AccessToken的工具类 import com alibaba fastjson2 JSON import com alibaba fastjson2 JSONObject import org springfra
  • 《数据结构初阶》用队列实现栈&&用栈实现队列的细致解析

    纵有千古 横有八方 目录 一 本章重点 二 队列实现栈 三 栈实现队列 四 解题思路总结 一 本章重点 用两个队列实现栈 用两个栈实现队列 解题思路总结 二 队列实现栈 我们有两个队列 入栈数据1 2 3 可以将数据入队列至队列一或者队列二
  • 如何让微pe上网_如何用U盘重装系统

    现如今电脑普及程度已经涉及到我们生活中的方方面面 日常生活和工作都离不开电脑 作为一个Window使用者 遇到问题时 能自己独立重装操作系统 是一件很有成就的事情 U盘重装系统是目前比较流行和简单的方法 比过去的使用光盘更加简易 小白也能轻
  • JavaScript-运算符篇

    目录 一 算数运算符 二 递增和递减运算符 1 前置递增 2 后置递增 三 比较运算符 四 逻辑运算符 1 逻辑与 2 逻辑或 3 逻辑非 5 短路运算 逻辑中断 6 赋值运算符 7 运算符优先级 8 流程控制 1 顺序机构 2 分支结构
  • 小朋友高矮排列-华为OD

    题目描述 现在有一队小朋友 他们高矮不同 我们以正整数数组表示这一队小朋友的身高 如数组 5 3 1 2 3 我们现在希望小朋友排队 以 高 矮 高 矮 顺序排列 每一个 高 位置的小朋友要比相邻的位置高或者相等 每一个 矮 位置的小朋友要
  • java.sql.SQLException: Access denied for user ‘root‘@‘localhost‘ (using password: YES)

    错误如下所示 查了一下发现是配置文件中的数据库密码错了 并且在代码生成器中 也要修改数据库 在查资料时发现 如果出现的错误是using password YES 那么应该是密码输错了 java sql SQLException Access
  • 深度学习实战12(进阶版)-利用Dewarp实现文本扭曲矫正

    大家好 我是微学AI 今天给大家介绍一下深度学习实战12 进阶版 利用Dewarp实现文本扭曲矫正 我们在生活中会看到一些拍摄扭曲的图片 我们在通过OCR识别的时候 因为扭曲的厉害 而无法识别 我们需要对图片进行处理 文件图像的变形有扭曲
  • HarmonyOS学习路之开发篇—多媒体开发(媒体数据管理开发)

    一 媒体数据管理开发概述 HarmonyOS媒体数据管理模块支持多媒体数据管理相关的功能开发 常见操作如 获取媒体元数据 截取帧数据等 在进行应用的开发前 开发者应了解以下基本概念 PixelMap PixelMap是图像解码后无压缩的位图
  • Javascirp异步编程

    在上一篇彻底弄清Javascirpt中的同步和异步一问当中 介绍了Javascirp代码执行的概念 同步和异步的原理 学习过Javascript语言的同学都知道 从Javascript诞生之日起 就是一门单线程 非阻塞的脚本语言 Javas