Promise, async, await 学习

news2024/12/23 14:21:33

异步编程简介:

介绍:异步编程是一种编程范式,旨在提高程序的性能和响应能力。该模型允许程序在执行某些任务时,不必等待这些任务完成就可以进行下一步操作,从而提高了程序的效率。

作用:异步编程通常用于涉及网络请求、文件读写、数据库查询等I/O密集型操作,以及高计算量的任务。在传统的同步编程中,这些操作会阻塞程序的执行,导致程序变慢或失去响应。而使用异步编程可以使这些I/O操作并行执行,从而提高程序的性能和响应能力。


并发 Concurrency、 并行 Parallelism、异步 Asynchronous、同步 Synchronous 的区别

(1)并发 Sancufrericy :代表计算机能够同时执行多项任务

计算机怎么做到并发 Concurrency 

(1)对于单核处理器,计算机可以通过分配时间片的方式——让一个任务运行一段时间,然后切换另外一个任务,再运行一段时间,不同的任务会这样交替往复的一直执行下去。——>这个过程也被称作是进程或者线程的上下文切换(context switching)

(2)对于多核处理器,可以在不同的核心上真正并行地执行任务,而不用通过分配时间片的方式运行——> 并行(parallelism)


同步和异步是两种不同的编程模型

(1)"同步” Synchronous 代表需要等到必须前一个任务执行完毕之后,才能进行下一个任务。因此在同步中并没有并发或者并行的概念。

(2)异步 Asynchronous 则代表不同的任务之间并不会相互等待、先后执行,即执行任务A时,也可以同时执行任务B

一个典型实现异步的方式则是通过多线程编程

多线程 Multithreoding : 创建多个线程并且启动他们,在多核的环境下,每个线程就会被分配到独立的核心上运行,实现真正的并行。

如果使用单核心处理器,或者通过设置亲和力(AfFnty) 强制将线程绑定到某个核心上

操作系统则会通过分配时间片的方式来执行这些线程,不过这些线程依然是在“并发”地执行Javascript 本身是没有多线程的概念的,不过通过它的函数回调(function callback)机制,依然能够做到单线程的“并发”。

例:通过 fetch() 函数 同时访问多个网络资源

⭕注意:

虽然主程序和回调函数看起来是同时进行的,但它们依然是运行在同一个线程中。

多线程编程、单线程的异步编程如何选择

(1)单线程的异步编程:对于I / O 密集的应用程序,比如 web 应用就会经常执行网络操作,数据库访问,这类应用就非常适合使用异步编程的方式。

如果是使用多线程的方式,则可能浪费系统资源(如下图)

因为每个线程的绝大多数时间都是在等待这些 I / O 操作,而线程自身会占用额外的内存(线程内存开销,线程切换开销还有线程资源竞争问题)

(2)多线程编程:

多线程编程则非常适合于计算量密集的应用,如视频图像处理,科学计算等。它能够让每一个 CPU 核心发挥最大的功效,而不是消耗在空闲的等待上。


JavaScript 中有两种实现异步的方式

(1)回调函数  Callback Function

可以使用 setTimeout() 让一个函数在指定的时间后执行,这个函数本身会立刻返回,程序紧接着会执行之后的代码,而传入的回调函数则会等到预定的时间才会执行

⭕注意:

  1. 这里的()=>是箭头表达式,相当于函数定义的简化写法
  2. Javascript 从设计之初就是一个单线程的编程语言 

即便看上去这里的回调函数和主程序在并发执行,但它们都运行在同一个主线程中。实际上主线程中还运行了我们写的其它代码,包括界面逻辑、网络请求、数据处理等等等等。虽然只有单个线程在执行,但这种单线程的异步编程方式其实有诸多优点。

由于所有操作都运行在同一个线程中,因此我们无须考虑线程同步或者资源竞争的问题,并且从源头上避免了线程之间的频繁切换。从而降低线程自身的开销。

缺点:

回调函数虽然简单好理解,但有一个明显的缺点:需要依次执行多个异步操作,会变成回调地狱 Callback Hell ——整个程序会一层接着一层的嵌套下去,可读性会非常差。


(2)Promise

Promise 就是为了解决这个问题——请求会在未来某个时刻返回数据,随后可以调用它的然后方法并传递一个回调函数。

Promise的API中的fetch就是很好的例子:

fetch 用来发起一个请求来获取服务器数据,可以用它动态更新页面的内容(即AJAX 技术 Asynchronous JavaScript and XML)

如果请求成功完成,则回调函数会被调起,请求的结果也会以参数的形式传递进来

而且  Promise的优点在于它可以用一种链式结构将多个异步操作串联起来!——链式调用 Chaining

response.json() 方法 也会返回一个 Promise,代表在未来某个时刻,将返回的数据转换成 JSON 格式。

如果想要等到它完成之后再执行其它的操作,可以在后面追加一个 then,然后执行接下来的代码。

Promise的链式调用避免了代码的层层嵌套,即便有很长的链,代码也不过是向下方增长而并非向右,因此可读性会提升不少。

使用异步操作也会遇到各种错误:各种网络问题或者返回的数据格式不正确等等

错误处理  Error Handling

如果想捕获这些错误,最简单的方法是附加一个 catch 在链式结构的末尾。

如果之前任意一个阶段发生了错误,那么将触发 catch ,之后的 then 将不会执行。这和同步编程中用到的 try/catch 块很类似。

类似的Promise还提供finally 方法,会在Promise 链结束之后调用。无论失败与否,都可以在这里做清理工作。

例如:如果我们用到了加载动画,则可以在这里关闭他。


新标准ECMA17 中加入的两个关键字 async、await

它们是基于 Promise之上的一个语法糖,使异步操作更加的简单。

首先我们需要使用 async 关键字将函数标记为异步函数。

异步函数就是指返回值为 Promise 对象的函数,比如之前用到的 fetch() 就是一个异步函数。

在异步函数中我们可以调用其它的异步函数,不过不再需要使用 then(),而是使用一个更加简洁的 await 语法。await 会等待 Promise 完成之后直接返回最终的结果。所以这里的 response 已经是服务器返回的响应数据了。

注意:await 虽然看上去会暂停函数的执行,但在等待的过程中,JavaScript 同样可以处理其它的任务,比如说更新界面,运行其他的代码等等。因为 await 底层是基于 Promise 和事件循环机制实现的。


await 使用时的陷阱

(1)分别去 await 这两个异步操作,虽然不存在逻辑错误,但这样写会打破这两个 fetch() 操作的并行。因为会等到第一个任务执行完成之后才开始执行第二个任务。

因此更高效的做法是将所有 Promise 用 Promise.all 组合起来。

 


(2)如果需要在循环中执行异步操作,是不能够直接调用 forEach 或者 map 这一类方法的,尽管我们在回调函数中写了 await,但这里的 forEach 会立刻返回,它并不会暂停等到所有异步操作都执行完毕

 如果我们希望等待循环中的异步操作都一一完成之后才继续执行,那我们还是应当使用传统的 for 循环。

更进一步,如果我们想要循环中的所有操作都并发执行 ——> for await

这里的 for 循环依然会等到所有的异步操作都完成之后才继续向后执行 。


(3)不能在全局或者普通函数中直接使用 await 关键字,await 只能被用在异步函数(asyncfunction)中。

如果我们想在最外层中使用 await,那么需要先定义一个异步函数,然后在函数体中使用它。

使用async和await 可以让我们写出更清晰、更容易理解的异步代码,因此我们几乎不再需要使用底层的Promise 对象

包括调用它的then() ,catch()函数等等。

即便是对于某些旧版本的浏览器(例如IE)不支持async语法 ,我们还是可以使用转译器将它们编译成旧版本也兼容的等效代码。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IPT2602协议-USB 快速充电端口控制器

产品描述: IPT2602是一款USB端口快速充电协议控制芯片。IPT2602智能识别多种快速充电协议,对手机等受电设备进行快速充电。IPT2602根据受电设备发送的电压请求能够精确的调整VBUS输出电压,从而实现快速充电。 IPT2602在调整5V输出电压前会自动…

10.5 认识XEDParse汇编引擎

XEDParse 是一款开源的x86指令编码库,该库用于将MASM语法的汇编指令级转换为对等的机器码,并以XED格式输出,目前该库支持x86、x64平台下的汇编编码,XEDParse的特点是高效、准确、易于使用,它可以良好地处理各种类型的指…

[硬件基础]-快速了解RS232串行通信

快速了解RS232串行通信 文章目录 快速了解RS232串行通信1、概述2、什么是串行数据通信?3、什么是RS232?4、RS232应用5、RS232如何工作?6、RS232协议基础6.1 电压与逻辑表示6.2 数据编码6.3 起始位和停止位6.4 奇偶校验位6.5 波特率6.5 RS232电…

掌握 SwiftUI 中的 ScrollView

文章目录 前言scrollTransition 修饰符ScrollTransitionPhase弹性动画总结 前言 SwiftUI 框架的第五个版本引入了许多与 ScrollView 相关的新 API,使其比以前更强大。本周将开始介绍 ScrollView 在 SwiftUI 中的新功能系列文章,首先我们将讨论滚动过渡。…

【LeetCode: 918. 环形子数组的最大和 | 动态规划】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

关联规则挖掘(上):数据分析 | 数据挖掘 | 十大算法之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…

【全方位带你配置yolo开发环境】快速上手yolov5

本文用于记录yolo开发环境的配置,以及我在配置中出现的各种问题,以供大伙参考。💥💥💞💞欢迎来到本博客❤️❤️💥💥 本人持续分享更多关于电子通信专业内容以及嵌入式和单片机的知识…

阿里云服务器ECS详细介绍_云主机_服务器托管_弹性计算

阿里云服务器ECS英文全程Elastic Compute Service,云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务,阿里云提供多种云服务器ECS实例规格,如经济型e实例、通用算力型u1、ECS计算型c7、通用型g7、GPU实例等,阿里云服务器网分享阿…

使用css制作3D盒子,目的是把盒子并列制作成3D货架

1. 首先看效果&#xff08;第一个五颜六色的是透明多个面&#xff0c;第2-3都是只有3个面是我实际需要的&#xff0c;右边的有3个并列的正方体与3个并列的长方体&#xff09;&#xff1a; 长方体与正方体&#xff0c;所有代码&#xff1a; <!DOCTYPE html> <html lan…

汽车网络安全--安全芯片应用场景解析

​在聊汽车网络安全时,最先想到的就是使用芯片内置HSM,比如说英飞凌TC2xx系列的HSM、瑞萨RH850的ICU、NXP的HSE等等;实际上除了内置HSM,还有外置HSM(通过UART、SPI等通信)、安全存储芯片等等。而这些芯片统称为安全芯片。 安全芯片的主要作用是为整个系统建立起一个可信的…

【Java】类和接口的区别

1. 类和类的继承关系&#xff08;一个类只能单继承一个父类&#xff0c;不能继承n多个不同的父类&#xff09; 继承关系&#xff0c;只能单继承&#xff0c;但可以多层继承 2. 类和接口的实现关系&#xff08;一个类可以实现n多个不同的接口&#xff09; 实现关系&#xff0c;可…

【QT开发笔记-基础篇】| 第四章 事件QEvent | 4.4 鼠标按下、移动、释放事件

本章要实现的整体效果如下&#xff1a; QEvent::MouseButtonPress ​ 鼠标按下时&#xff0c;触发该事件&#xff0c;它对应的子类是 QMouseEvent QEvent::MouseMove ​ 鼠标移动时&#xff0c;触发该事件&#xff0c;它对应的子类是 QMouseEvent QEvent::MouseButtonRel…

golang gin框架1——简单案例以及api版本控制

gin框架 gin是golang的一个后台WEB框架 简单案例 package mainimport ("github.com/gin-gonic/gin""net/http" )func main() {r : gin.Default()r.GET("/ping", func(c *gin.Context) {//以json形式输出&#xff0c;还可以xml protobufc.JSON…

网络安全黑客究竟是什么?

“网络安全”是指任何活动旨在保护您的网络和数据的可用性和完整性。它包括硬件和软件技术。有效的网络安全管理对网络的访问。它针对的是一种不同的威胁,阻止他们进入或在您的网络传播。 网络安全是如何工作的呢? 网络安全结合多层防御的优势和网络。每个网络安全层实现政策…

前端TypeScript学习day01-TS介绍与TS常用类型

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 TypeScript 介绍 TypeScript 是什么 TypeScript 为什么要为 JS 添加类型支持&#xff1f; TypeScript 相…

【Redis】基础数据结构-quicklist

Redis List 在Redis3.2版之前&#xff0c;Redis使用压缩列表和双向链表作为List的底层实现。当元素个数比较少并且元素长度比较小时&#xff0c;Redis使用压缩列表实现&#xff0c;否则Redis使用双向链表实现。 ziplist存在问题 不能保存过多的元素&#xff0c;否则查找复杂度…

vue-devtools插件安装

拓展程序连接 链接&#xff1a;https://pan.baidu.com/s/1tEyZJUCEK_PHPGhU_cu_MQ?pwdr2cj 提取码&#xff1a;r2cj 一、打开谷歌浏览器&#xff0c;点击扩展程序-管理扩展程序 二、打开开发者模式&#xff0c;将vue-devtools.crx 拖入页面&#xff0c;点击添加扩展程序 成…

三、【色彩模式与颜色填充】

文章目录 Photoshop常用的几种颜色模式包括&#xff1a;1. RGB模式2. CMYK模式3. 灰度模式4. LAB模式5. 多通道模式 Photoshop颜色填充1.色彩基础2.拾色器认识3.颜色填充最后附上流程图&#xff1a; Photoshop常用的几种颜色模式包括&#xff1a; 1. RGB模式 详细可参考&…

mysql-sql执行流程

sql执行流程 MYSQL 中的执行流程 MYSQL 中的执行流程 sql 执行流程如下图

【Qt基础篇】信号和槽

文章目录 一些常见的bug&#xff1a;字符集不对产生的错误VS平台中文乱码 QT的优点关于.pro文件QtCreator快捷键最简单的qt程序按钮的创建对象模型**Qt窗口坐标**体系信号和槽机制connect函数系统自带的信号和槽案例&#xff1a;实现点击按钮-关闭窗口的案例 自定义信号和槽案例…