如何避免 async/await 地狱

学会promise和async/await的巧用小妙招 async/await 和 Promise 是 JavaScript 中处理异步操作的两种方式。async/await 是基于 Promise 的语法糖,它可以更方便地编写异步代码。在使用 async/await 时,可以使用 try/catch 语句来处理异步操作的错误。在使用 Promise 时,可以使用 then 和 catch 方法来处理异步操作的结果和错误。async/await是基于Promise的一种更加简洁和可读性更高的异步编程模式,可以避免回调地狱,使得代码更加简洁和易于理解。 阅读详情

简评:async/await 写着很爽,不过要注意这些问题。

async/await 让我们摆脱了回调地狱,但是这又引入了 async/await 地狱的问题。

这里写图片描述

什么是 async/await 地狱

在 Javascript 中进行异步编程的时候,人们总是使用很多 await 语句,很多时候我们的语句并不需要依赖于之前的语句,这样就会导致性能问题。

async/await 地狱的例子

我们试着写一个购买披萨和饮料的程序:

(async () => {
  const pizzaData = await getPizzaData()    // async call
  const drinkData = await getDrinkData()    // async call
  const chosenPizza = choosePizza()    // sync call
  const chosenDrink = chooseDrink()    // sync call
  await addPizzaToCart(chosenPizza)    // async call
  await addDrinkToCart(chosenDrink)    // async call
  orderItems()    // async call
})()

这段代码运行没有问题。但是不是一个好的实现,因为这增加了不必要的等待。

说明

我们已经将我们的代码封装在异步 IIFE 中,按照下面的顺序执行:

  1. 得到披萨名单
  2. 获取饮料列表
  3. 从列表中选择一个披萨
  4. 从列表中选择一种饮料
  5. 将选中的披萨加入购物车
  6. 将选择的饮品加入购物车
  7. 订购购物车中的物品

问题

这里有个问题为什么从列表中选择披萨这个动作要等待获取饮料列表?这两个是没什么关联的操作。其中的关联操作有两组:

获取披萨列表 -》 选择披萨 -》 选择披萨加入购物车

获取饮料列表 -》 选择饮料 -》 选择饮料加入购物车

这两组操作应该是并发执行的。

再来看一个更差的例子
这个 Javascript 代码片段将购物车中的商品并发出订购请求。

async function orderItems() {
  const items = await getCartItems()    // async call
  const noOfItems = items.length
  for(var i = 0; i < noOfItems; i++) {
    await sendRequest(items[i])    // async call
  }
}

这种情况 for 循环必须等待 sendRequest() 函数完成才能继续下一次迭代。但是,我们并不需要等待。我们希望尽快发送所有请求。然后我们可以等待所有请求完成。

现在你应该已经对 async/await 地狱有跟多的了解,现在我们再来考虑一个问题

如果我们忘记 await 关键字会怎么样?

如果在调用异步函数忘记使用 await,这意味着执行该功能不需要等待。异步函数将直接返回一个 promise,你可以稍后使用。

(async () => {
  const value = doSomeAsyncTask()
  console.log(value) // an unresolved promise
})()

或者是程序不清楚你想要等待函数执行完,直接退出不会完成这个异步任务。所以我们需要使用 await 这个关键字。

promise 有一个有趣的属性,你可以在某行代码中获取 promise,然后在其他地方中等待它 resolve,这是解决 async/await 地狱的关键。

(async () => {
  const promise = doSomeAsyncTask()
  const value = await promise
  console.log(value) // the actual value
})()

如你所见 doSomeAsyncTask 直接返回一个 Promise 同时这个异步函数 doSomeAsyncTask 已经开始执行,为了得到 doSomeAsyncTask 的返回值,我们需要 await 来告诉

应该如何避免 async/await 地狱

首先我们需要知道哪些命名是有前后依赖关系的。
然后将有依赖关系的系列操作进行分组合并成一个异步操作。
同时执行这些异步函数。
我们来重写这写例子:

async function selectPizza() {
  const pizzaData = await getPizzaData()    // async call
  const chosenPizza = choosePizza()    // sync call
  await addPizzaToCart(chosenPizza)    // async call
}

async function selectDrink() {
  const drinkData = await getDrinkData()    // async call
  const chosenDrink = chooseDrink()    // sync call
  await addDrinkToCart(chosenDrink)    // async call
}

(async () => {
  const pizzaPromise = selectPizza()
  const drinkPromise = selectDrink()
  await pizzaPromise
  await drinkPromise
  orderItems()    // async call
})()

// Although I prefer it this way 

(async () => {
  Promise.all([selectPizza(), selectDrink()].then(orderItems)   // async call
})()

我们将语句分成两个函数。在函数内部,每个语句都依赖于前一个语句的执行。然后我们同时执行这两个函数 selectPizza()和selectDrink() 。

在第二个例子中我们需要处理未知数量的 Promise。处理这个问题非常简单,我们只需要创建一个数组将所有 Promise 存入其中,使用 Promise.all() 方法并行执行:

async function orderItems() {
  const items = await getCartItems()    // async call
  const noOfItems = items.length
  const promises = []
  for(var i = 0; i < noOfItems; i++) {
    const orderPromise = sendRequest(items[i])    // async call
    promises.push(orderPromise)    // sync call
  }
  await Promise.all(promises)    // async call
}
async / await 解决回调地狱 async / await 是ES7的新增语法,也是回调地狱的终极解决方案,我们可以用async / await语法把异步代码写的看起来像同步代码。        本文主要是对async / await 的介绍及解决回调地狱的方法,关于Promise的详细介绍及Promise解决回调地狱,见:       [ ES6之Promise的介绍及解决回调地狱 ] async / await的介绍: async写在函数的前面,就可以该函数变成一个异步函数; await是写在异步函数里面的关键; await关键字后面必须是一个Promise对象; 有了以上三个条件,我们就可以把本该在promise的t 立即下载

相关推荐

物联网定位技术|实验报告|实验一 Wi-Fi指纹定位

全球定位系统是迄今为止应用最为成功的地位系统,具备高精度的定位能力,但在室内和高楼密布的城区等信号遮挡严重的密集环境中,由于接受机捕获不到足够强度的卫星信号,GPS的定位质量难以保证甚至无法完成定位,使其可用性受到严重制约。由于室内环境下都普及了WiFi,因此利用WiFi进行定位无需额外部署硬件设备,是一个非常节省成本的方法。

m0_57656758的博客 3356

如何避开async/await地狱

async/await把我们从回调地狱中解放了出来,但是随之而来的是大家对它的滥用,导致了async/await地狱的诞生。 在这篇文章里我将会解释什么是async/await地狱以及分享一些方法去避开它。 什么是async/await地狱? 当我们在编写JavaScript异步代码的时候,常常会在一个接着一个函数调用前添加await关键字,影响了函数的调用。因为在一般情况下,下一个函数的调用并...

前端技术小哥 577

别再瞎猜了!Fluent瞬态计算时间步长到底设多少?一个公式+实战案例搞定

本文详细解析了Fluent瞬态计算中时间步长的设置方法,通过黄金公式和实战案例,帮助工程师准确确定时间步长,避免计算发散和资源浪费。文章还介绍了动态调整策略和典型工程场景的参数优化,提升仿真效率和精度。

weixin_42638178的博客 426

异步函数执行的时候可以不用await吗

是的,您可以在不使用await关键字的情况下执行异步函数。异步函数 (async函数) 总是返回一个Promise对象,不论是否使用await。使用await的主要目的是为了等待Promise的结果,并以同步的方式编写异步代码。

m0_57236802的博客 3174

嵌入式Linux&Android开发-环境搭建

目录 一、环境要求 二、相关软件&SDK下载 三、环境安装 3.1 VMware Worksation 3.2 Ubuntu1804 3.3 VSCode安装 3.4 Samba服务器搭建 一、环境要求 编译 Android 对机器的配置要求较高: 64 位 CPU 大于12GB 物理内存+交换内存(最好16GB以上) 30GB 空闲的磁盘空间用于构建,源码树另外占用大约 25GB, 如果要编译源码则还需要 150GB 的磁盘空间。 RK官方推荐使用 Ubuntu 16..

嵌入式成长手册 548

基于 YOLOv26 的校园安全监控系统:多场景应用

本文提出了一种基于YOLOv26的校园安全监控系统,采用多场景应用架构实现对校园安全的智能监测。系统核心技术包括YOLOv26目标检测、DeepSORT目标跟踪、区域安全定义和行为分析等模块,通过边缘计算平台实现实时处理。研究构建了包含多种校园场景的专业数据集,并采用数据增强技术提升模型性能。系统可检测人员、车辆和物品等目标,分析其行为轨迹,评估安全风险并触发告警。实验结果表明,该系统能有效识别校园安全隐患,为安全管理提供智能化解决方案。

一键难忘的博客 503

只使用async 不使用await_js中async和await的基本使用

async和await是在es7中的内容,不过现在主流浏览器都支持,今天我们就来说说怎么用。首先你得先了解:es6中的promise,请自行了解,此篇文章不谈。async和await是用来处理异步操作的,把异步变为同步的一种方法。async声明一个function来表示这个异步函数,await用于等待函数中某个异步操作执行完成。async返回的是一个promise对象,返回值可在promise中的...

weixin_39878698的博客 4501

Python全栈入门到实战【基础篇 19】函数进阶:默认参数、递归函数与偏函数应用

本文深入探讨Python函数进阶的三大核心知识:默认参数、递归函数与偏函数。针对默认参数,揭示了可变对象作为默认值的陷阱,提出使用None替代的方案;解析递归函数的三大要素(终止条件、递归调用、问题拆解),并通过阶乘和斐波那契数列示例演示实现方法,同时给出尾递归和缓存装饰器两种优化策略;最后介绍偏函数如何通过functools.partial固化参数简化调用。这些技巧能显著提升函数在复杂场景下的灵活性与复用性,帮助开发者编写更高效的Python代码。

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 3864

JS核心-异步编程中的async/await

JS的语法糖await/async包装Promise,使得异步代码看起来像同步代码的风格。同时介绍了async函数执行的流程,以及使用await可能带来的问题。

输出与提升 678

Qt5.14.2开发Mqtt应用程序

然后,你就做不下去了…很明显,大部分博主写的东西不是缺头就是缺尾,带偏了许多读者。,因此我们需要clone的是这个分支版本,而不是这个默认的。然后将编译产物中include里的所有.h文件复制到。下载完后直接默认安装即可,这一步没什么好说的。看到了没,这个才是正确的操作方式,而主线的。信号来判断,自行实现自己的槽函数。然后选择构建方式,这里我选择的是。信号来判断自行实现自己的槽函数。信号来判断自行实现自己的槽函数。源代码,如下图所示,双击打开。收到下行消息时,可以通过连接。

Bruce.yang的嵌入式之旅 2310

激光雷达与相机外参标定(附open3d python代码)

现在的激光雷达与相机的标定程序基本都是Ubuntu框架下面的,并且都是C++代码,需要安装的依赖也比较复杂,于是自己写了一个python版本的标定程序,依赖非常简单,Windows系统也可以运行。我这里用的大疆的雷达,点比较密集,更容易用我这种方法标定,旋转的16,32线的雷达也可以用这种方法标定,只是标定点会相对难选取一些。2 手动在点云上选取N个标定点(每个点都对应图像上的点,顺序也要一致)3 通过PNP方法计算出二者的旋转投影矩阵,也就是外参矩阵。1 手动在图像上面选取N个标定点。

三维点云技术探索 3412

Win11 秒速搜索指南:PowerToys Run + Everything 复刻 macOS Spotlight 核心体验

在 Windows 11 中,文件搜索慢、索引不完整是长期困扰用户的痛点,而 macOS 的 Spotlight 之所以高效,不仅在于极速定位文件,更在于它将启动应用、计算、查询等操作统一到一个轻量入口。要获得类似体验,关键在于理解底层原理:Everything 直接读取 NTFS 主文件表(MFT)与 USN 日志,跳过传统索引服务,实现毫秒级全盘文件名检索;PowerToys Run 则作为微软官方的命令面板,提供应用启动、计算器、系统设置等扩展能力,并可无缝调用 Everything 作为文件搜索引擎

weixin_33826609的博客 328

即插即用系列(代码实践) | CVPR 2025 WPFormer:小波与原型增强Transformer——表面缺陷检测SOTA,专治弱缺陷与杂乱背景

摘要:本文提出了一种基于小波变换和原型增强的Transformer模型(WPFormer),用于像素级表面缺陷检测。该模型针对工业场景中微弱缺陷难以识别和杂乱背景干扰严重的问题,创新性地将小波变换引入Transformer的注意力机制,通过频域信息分离噪声与边缘特征,同时利用原型向量引导查询,实现了更精准的缺陷定位。核心模块包括小波增强交叉注意力(WCA)和原型引导交叉注意力(PCA),适用于工业缺陷检测、伪装目标检测和医学图像分割等任务。代码已开源,支持即插即用集成到现有框架中。

分享顶会顶刊论文即插即用模块 301

如何避免 await/async 地狱

原文地址:How to escape async/await hell 译文出自:夜色镇歌的个人博客 async/await 把我们从回调地狱中解救了出来,但是如果滥用就会掉进 async/await 地狱。 本文中我会解释一下什么是 async/await 地狱,并会分享几个技巧去避免。 啥是 await/async 地狱 异步 Javascript 编程中,我们通常会写许多 a...

weixin_30564901的博客 172

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

避免回调地狱的解决方案 async/await:用同步的方式去写异步代码

避免回调地狱的终极解决方案 async/await:用同步的方式去写异步代码

小猿同学628的博客 808

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

async/await:在前端开发中的应用

async、await 是 ES8(ECMAScript2017)引入的新语法,用来简化 Promise 异步操作。使用async和await可以让异步代码看起来几乎和同步代码一样,从而大大简化了代码的结构和可读性。你不再需要嵌套回调函数或链接多个Promise,代码变得更加直观和线性。async 用来声明一个 function 是异步的,await 用来等待一个异步方法执行完成。await 只能出现在 async 函数中。async 声明的函数,返回的结果是一个 Promise 对象。

outstanding木槿 1676

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

一次性让你懂async/await

文章目录一次性让你懂async/await,解决回调地狱什么是async?怎么用await是什么?更新后话 一次性让你懂async/await,解决回调地狱 什么是async? 欢迎留言讨论 async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。相较于 Generator,async 函数的改进在于下面四点: 内置执行器。Generator 函数的执行必须依靠执行器,而 async 函数自带执行器,调用方式跟普通函数的调用一样 更好

song854601134的博客 6667

前端JavaScript篇之对async/await 的理解、async/await的优势、async/await对比Promise的优势

async/await是JavaScript中处理异步操作的一种语法糖。它让我们可以用同步的方式写异步代码,使得代码更易读懂。

星辰迷上大海的博客 2135

理解异步函数async和await的用法

async作为一个关键字放在函数前面,表示该函数是一个异步函数,异步函数意味着该函数的执行不会阻塞后面代码的执行;而 await 用于等待一个异步方法执行完成

铁锤妹妹的博客 14万+

深入理解async/await来处理异步

目前async/await已经被标准化,我们需要尽快将学习进程提上日程。 先说一下async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为async就是异步的意思,异步函数也就意味着该函数的执行不会阻塞后面代码的执行。下面写一个async函数: async function timeout() {   return 'hello world'; } 复制代码 语法很简单,就是在函数前面加上async关键字,来表示它是异步的,那怎么调用呢?async函数也是函数,平时我们怎么使用

Ben_Simons 979

vue中使用async和await来实现同步和异步

用async/await 来处理异步 近期项目中大量使用async,从服务器获取数据,解决一些并发传参问题。代码很简单。在此也看了一些博客,现在async/await已经大范围让使用,是时候总结一波啦。 先说一下async的语法,它作为一个关键字放在函数前面,用于表示函数是一个异步函数,因为async就是异步的异步,异步函数也就是意味着这个函数的执行不会阻塞后面代码的执行。简单的写一个async函数 async function hello(){ return 'hello world'; }

aaron9185的博客 1万+

async / await 详解

当遇到 await,会先暂停 await 及后边代码的执行,直到 Promise 的状态发生改变后,才会继续执行 await 以及后边的任务await 本质是 then 的语法糖,其实是个微任务在 await new Promise 中如果包含一个定时器,定时器的回调函数中写 resolve() 或者reject(),那么这个定时器是个宏任务,会在宏任务队列排队完成后,再改变 Promise 的状态,然后 await 才能执行,再取消阻塞。

When you can't win by being better, you can win by being different. 1722

解析async/await promise then

转:https://www.cnblogs.com/SamWeb/p/8417940.html 好文章啊,痛哭流涕,好多不懂得的地方明了了 用 async/await 来处理异步 昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简洁,同时async/await 已经被标准化,是时候学习一下了。 先说一下async的用法,它作为一个关键字放到函数前面,...

weixin_43553234的博客 2282
上一篇: 命令行里打 cd 简直是浪费生命
下一篇: 工程师如何在面试中脱颖而出
极光推送
博客等级 码龄14年 109粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值