一盏茶的功夫帮你彻底搞懂JavaScript异步编程从回调地狱到async/await

 🎬 江城开朗的豌豆:个人主页

 🔥 个人专栏 :《 VUE 》 《 javaScript 》

⛺️ 生活的理想,就是为了理想的生活 !

在这里插入图片描述

目录

📘 1. 引言

📘 2. 使用方法

📘 3. 实现原理

📘 4. 写到最后


 

📘 1. 引言

在深入讨论 async/await 之前,我们需要了解一下 JavaScript 的单线程和非阻塞的特性。JavaScript 是单线程的,也就是说在任何给定的时间点,只能执行一个操作。然而,对于需要大量时间的操作(例如从服务器获取数据),如果没有适当的管理机制,这种单线程特性可能会导致应用程序的阻塞。为了解决这个问题,JavaScript 引入了回调函数和后来的 Promise,用来管理这些异步操作。

然而,回调函数Promise 还是存在一些问题。回调函数很容易导致 "回调地狱",因为每个异步操作都需要一个回调函数,如果有很多这样的操作,代码就会变得非常混乱。Promise 解决了这个问题,让异步代码更加直观,但是,Promise 的链式调用有时候还是显得不够直观。

为了结合Promise和生成器的优势,Async/awaitECMAScript 2017(ES8)中被引入。它通过async函数和await表达式提供了一种更加直观和简洁的方式来编写异步代码,消除了回调函数和手动管理Promise的需要。

📘 2. 使用方法

Async/await的使用方法非常简单明了,主要涉及两个关键字:async和await。

  • async关键字:用于声明一个async函数,它返回一个Promise对象。在async函数内部,我们可以使用await关键字来暂停函数的执行,等待一个异步操作的完成,并获得其结果。在这个过程中,async函数会暂时释放线程的控制权,使其他代码可以继续执行。

  • await关键字:用于暂停async函数的执行,等待一个Promise对象的完成,并返回其解析的值。它只能在async函数内部使用。当使用await表达式时,代码的执行会暂停,直到Promise对象被解析或拒绝。

下面是一个示例,展示了Async/await的使用方法:

async function getData() {try {const response = await fetch('https://api.example.com/data');const data = await response.json();return data;} catch (error) {console.error('Error:', error);throw error;}
}getData().then(data => console.log('Data:', data)).catch(error => console.error('Error:', error));

在上面的示例中,getData函数是一个async函数,它等待fetch函数返回的Promise对象,并使用await关键字获取响应的数据。最后,我们使用.then方法处理返回的数据,或使用.catch方法处理可能发生的错误。

📘 3. 实现原理

Async/Await 的实现原理其实就是 Generator + Promise。我们知道 Generator 可以在 yield 关键字处暂停和恢复执行,Promise 可以处理异步操作,两者结合在一起,就可以实现一个类似于 async/await 的功能。


function promiseFn() {return new Promise((resolve) => {setTimeout(() => {resolve('promise resolved');}, 2000);});
}
function* genFn() {let result = yield promiseFn();console.log(result);
}
function asyncToGenerator(generator) {let gen = generator();return new Promise((resolve, reject) => {function step(key, arg) {let result;try {result = gen[key](arg);} catch (error) {return reject(error);}const { value, done } = result;if (done) {return resolve(value);} else {return Promise.resolve(value).then(val => {step('next', val);}, err => {step('throw', err);});}}step('next');});
}
asyncToGenerator(genFn);

在上述代码中,我们首先创建了一个 promiseFn 函数,该函数返回一个在 2 秒后解析的 Promise。然后,我们创建了一个 Generator 函数 genFn,在该函数内部,我们使用 yield 关键字暂停执行并等待 promiseFn 的结果。最后,我们创建了一个 asyncToGenerator 函数,该函数接受一个 Generator 函数作为参数,并返回一个新的 Promise,这个 Promise 的解析值就是 Generator 函数的返回值。

📘 4. 写到最后

总的来说,Async/await是一种使得JavaScript异步编程变得更加友好和易用的语法特性。它帮助开发者以一种更加清晰和简洁的方式处理异步操作,提升了代码的可读性和维护性。对于那些曾经苦于回调地狱的开发者来说,Async/await是一种令人期待的改变,它让我们可以更加舒心地编写异步代码。

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 自定义PopupWindow,实现下拉框

1、效果图 2、前言 1、页面由 MagicIndicator ViewPager2 Fragment 实现; 2、下拉框是基于WindowManager实现; 3、我使用PopupWindow实现下拉框时,发现一个问题,PopupWindow 在窗口显示的情况下,无法直接从外部修…

(c语言进阶)指针的进阶

一.字符指针 1.一般应用 (1)%c的应用 (2)%s的应用 字符指针没有权限通过解引用去改变指针指向的值 2.笔试题 题目:判断输出结果 int main() { const char* p1 "abcdef"; const char* p2 "…

无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同

“/”应用程序中的服务器错误。 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Se…

【云备份】

文章目录 [toc] 1 :peach:云备份的认识:peach:1.1 :apple:功能了解:apple:1.2 :apple:实现目标:apple:1.3 :apple:服务端程序负责功能:apple:1.4 :apple:服务端功能模块划分:apple:1.5 :apple:客户端程序负责功能:apple:1.6 :apple:客户端功能模块划分:apple: 2 :peach:环境搭建…

[VC++]圆形进度条

[VC]圆形进度条 源码开发环境:VC6.0 WIN10 64位下编译通过利用绘制饼图的原理,来制作的圆形进度条,可以显示百分比。软件运行截图如下: 附件源码下载(点击下载)

基于ensp的园区网络搭建综合实验

目录 🕒 1. 技术介绍🕒 2. 需求分析🕘 2.1 项目背景和需求🕘 2.2 项目需求分析 🕒 3. 网络结构设计🕒 4. 网络拓扑规划🕒 5. 网络设备基本配置🕘 5.1 规划VLAN🕘 5.2 MST…

【RK3588】YOLO V5在瑞芯微板子上部署问题记录汇总

YOLO V5训练模型部署到瑞芯微的板子上面,官方是有给出案例和转过详情的。并且也提供了Python版本的推理代码,以及C语言的代码。 但是,对于转换过程中的细节,哪些需要改?怎么改?如何改,和为什么…

Java中树形菜单的实现方式(超全详解!)

前言 这篇文中,我一共会用两种方式来实现目录树的数据结构,两种写法逻辑是一样的,只是一种适合新手理解,一种看着简单明了但是对于小白不是很好理解。在这里我会很详细的讲解每一步代码,主要是方便新人看懂&#xff0…

typescript: Builder Pattern

/*** file: CarBuilderts.ts* TypeScript 实体类 Model* Builder Pattern* 生成器是一种创建型设计模式, 使你能够分步骤创建复杂对象。* https://stackoverflow.com/questions/12827266/get-and-set-in-typescript* https://github.com/Microsoft/TypeScript/wiki/…

4.Docker 搭建 redis6

1.下载redis docker pull redis:6.2.62.创建需要挂载的宿主机文件夹 mkdir -p /data/redis/conf mkdir -p /data/redis/data3.配置redis 切换到/data/redis/conf文件夹下,创建redis.conf,复制redis.conf配置文件内容到redis.conf文件中,然后按下键盘 …

黑豹程序员-架构师学习路线图-百科:AJAX

文章目录 1、什么是AJAX2、发展历史3、工作原理4、一句话概括 1、什么是AJAX Ajax即Asynchronous(呃森可乐思) Javascript And XML(异步JavaScript和XML) 在 2005年被Jesse James Garrett(杰西詹姆斯加勒特&#xff09…

GD32F103x 定时器

1. 定时器的基本介绍 STM32的定时器主要分为三种:高级定时器、通用定时器、基本定时器。 即:高级定时器具有捕获/比较通道和互补输出,死区时间,通用定时器只有捕获/比较通道,基本定时器没有以上两者。 1. 基本定时…

网络安全:六种常见的网络攻击手段

1、什么是VPN服务? 虚拟专用网络(或VPN)是您的设备与另一台计算机之间通过互联网的安全连接。VPN服务可用于在离开办公室时安全地访问工作计算机系统。但它们也常用于规避政府审查制度,或者在电影流媒体网站上阻止位置封锁&#…

【React】深入理解React组件状态State

目录 一、何为State二、如何定义State三、如何判断是否为State四、如何正确使用State1、用setState修改State2、State的更新是异步的①、代码示例 3、State更新会被合并①、组件状态例子②、当只需要修改状态title时,只需要将修改后的title传给setState③、React会合…

Windows安装Node.js

1、Node.js介绍 ①、Node.js简介 Node.js是一个开源的、跨平台的JavaScript运行环境,它允许开发者使用JavaScript语言来构建高性能的网络应用程序和服务器端应用。Node.js的核心特点包括: 1. 事件驱动: Node.js采用了事件驱动的编程模型,通…

力扣 -- 647. 回文子串

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int countSubstrings(string s) {int ns.size();vector<vector<bool>> dp(n,vector<bool>(n));//无需初始化int ret0;//一定要从下往上填写每一行for(int in-1;i>0;i--){//每一行的i…

jvm--对象实例化及直接内存

文章目录 1. 创建对象2. 对象内存布局3. 对象的访问定位4. 直接内存&#xff08;Direct Memory&#xff09; 1. 创建对象 创建对象的方式&#xff1a; new最常见的方式、Xxx 的静态方法&#xff08;单例模式&#xff09;&#xff0c;XxxBuilder/XxxFactory 的静态方法Class 的…

CVE-2023-36845:Juniper Networks Junos OS EX远程命令执行漏洞

Juniper Networks Junos OS EX远程命令执行漏洞(CVE-2023-36845) 复现 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#…

UE4 自带体积云应用

新建空关卡 点击该选项 全部点击一遍 拖进场景

uniapp 在uni.scss 根据@mixin定义方法 、通过@include全局使用

在官方文档中提及到uni.scss中变量的使用&#xff0c;而我想定义方法&#xff0c;这样写css样式更方便 一、官方文档的介绍 根据官方文档我知道&#xff0c;在这面定义的变量全局都可使用。接下来我要在这里定义方法。 二、在uni.scss文件中定义方法 我在uni.scss文件中定义了…