async-await让你的异步代码更加优雅

从‘回调地狱’到‘优雅异步’:在Vue 3项目中用async/await重构那些老旧的callback代码 本文探讨了如何在Vue 3项目中通过async/await重构传统的回调函数代码,解决‘回调地狱’问题。从识别回调地狱的典型症状到Promise化改造,再到async/await实战应用,详细展示了如何提升代码可读性和维护性。结合Vue 3的Composition API,实现异步代码的优雅重构。 阅读详情

首先对于Promise不太熟悉的朋友建议可以先看一下我的这两篇关于Promise的文章

Promise用法详解一

Promise用法详解二

async-await和Promise的关系


async-await是promise和generator的语法糖。只是为了让我们书写代码时更加流畅,当然也增强了代码的可读性。简单来说:async-await 是建立在 promise机制之上的,并不能取代其地位。async和await最关键的用途是以同步的写法实现了异步调用。
 

基本语法

async function fn() {
    let result = await Math.random();
    console.log(result);// 0.10492893687819915
}
console.log(fn());// Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}


上述代码就是async-await的基本使用形式。有两个陌生的关键字async、await,同时函数执行结果返回了一个promise对象,这样一看似乎并没有什么特别之处。

 async


async用来表示函数是异步的,定义的函数会返回一个promise对象,可以使用then方法添加回调函数。

async function fn1() {
    return 666;
}
fn1().then(val => {
    console.log(val);// 666
});


若 async 定义的函数有返回值,return 666;相当于Promise.resolve(666),没有声明式的 return则相当于执行了Promise.resolve();

await


await 可以理解为是 async wait 的简写。await 必须出现在 async 函数内部,不能单独使用。

function badFn() {
    await Math.random();
}
badFn();// Uncaught SyntaxError: await is only valid in async function


await 后面可以跟任何的JS 表达式。虽然说 await 可以跟很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await的是 promise对象会造成异步函数停止执行并且等待 promise 的解决,如果等的是正常的表达式则立即执行。
 我们可以利用这一特性来实现一个sleep函数


 async-await 实现 sleep()函数

  function sleep(ms) {
        return new Promise(
            (resolve) => setTimeout(resolve, ms)
        );
    }
    async function test() {
        var temple = await sleep(1000);
        console.log(1111)
        return temple
    }
    test();
    //延迟1000ms输出了1111


 需求:此时我们有一个简单的需求,需要去依次去读取一些文件的内容。若用 ES5实现会有3层的回调,若用Promise 实现至少需要3个then。一个是代码横向发展,另一个是纵向发展。这里用async-await实现

const fs = require('fs')
function getFileByPath(fpath) {
    return new Promise(function (resolve, reject) {
        fs.readFile(fpath, 'utf-8', (err, dataStr) => {
            if (err) return reject(err)
            resolve(dataStr)
       })
   })
}

async function test() {
    let res1 = await getFileByPath('./1.txt');
    console.log(res1)
    let res2 = await getFileByPath('./2.txt');
    console.log(res2)
    let res3 = await getFileByPath('./3.txt');
    console.log(res3)
}
test()


运行,此时控制台依次输出文件一到三的内容。回看test函数,以同步的方式去书写异步逻辑,简直不要太爽。


不要滥用async-await


要选择合适的场景,还是那上面读取文件的例子来说,我还是需要读取三个文件,相互没有关联,只是需要三个文件全部读取完毕后提示即可。
此时你可能会说上面的可以实现需求啊。的确,不过此时就将异步的并发请求变成了阻塞式同步的操作了。严重影响效率,此时应该这样写。

async function test() {
    let res1 = getFileByPath('./1.txt');
    console.log(res1)
    let res2 = getFileByPath('./2.txt');
    console.log(res2)
    let res3 = getFileByPath('./3.txt');
    console.log(res3)
    await Promise.all([res1, res2, res3]);
    console.log('文件读取完成')
}



async-await只是promise的语法糖,还是需要用promise来实现。

 await必须在async函数上下文中

async function forBugDemo() {
    let arr = [1, 2, 3, 4, 5];
    arr.forEach(item => {
        await console.log(item);
    });
}
forBugDemo();// Uncaught SyntaxError: await is only valid in async function


如上await并未在async函数上下文中故报错。。


 正确写法如下

async function forDemo() {
    let arr = [1, 2, 3, 4, 5];
    for (let i = 0; i < arr.length; i ++) {
        await console.log(arr[i]);
    }
}
forDemo();

 

关于JavaScript 异步方案 async/await 从代码片段中不难看出 Promise 没有解决好的事情,比如要有很多的 then 方法,整块代码会充满 Promise 的方法,而不是业务逻辑本身,而且每一个 then 方法内部是一个独立的作用域,要是想共享数据,就要将部分数据暴露在最外层,在 then 内部赋值一次。虽然如此,Promise 对于异步操作的封装还是非常不错的,所以 async/await 是基于 Promise 的,await 后面是要接收一个 Promise 实例。服务端使用 Babel,最简单的方式是通过 require hook。 阅读详情

相关推荐

AB相增量式编码器以及STM32定时器编码器模式测速/测距离(HAL库)

编码器(Encoder)是一种用于测量旋转运动或位置的设备。编码器通常与定时器模块一起使用,以便在微控制器中获取和计算旋转的脉冲数量,从而确定物体的运动方向和距离。编码器在许多应用中都很有用,例如机器人运动控制、电机位置反馈和位置传感。STM32微控制器提供了多种类型的编码器支持,其中一种常见的编码器类型是增量编码器。增量编码器基于两个脉冲信号通道,通常称为A相和B相。当旋转发生时,这两个信号通道的相位关系会发生变化,从而可以计算出旋转方向和旋转的步数。

嵌入式软件工程师的博客 1万+

await is only valid in async function

这个错误的意思是await只能放到async函数内部,言下之意: await必须放到函数里 函数必须有async修饰符 错误1: 没有放到函数里 const myFun = async () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(1) },1000) }) } // 错误: 没有放在函数里 res1 = await myFun(); cons

胡聊前端的博客 4万+

多重共线性问题 -- 岭回归方法

概述 本篇博客分为三大部分,线性模型、多重共线性问题和岭回归。其中,线性模型中介绍了线性模型定义和普通最小二乘法对线性模型的拟合。第二部分,借由1987-2007年的人口、消费和科技对碳排放的影响的数据来说明多重共线性问题(包括如何从定性和定量两个方面判断多重共线性问题)和多重共线性问题对普通最小二乘估计的影响。第三部分,使用岭回归对第二部分中的多重共线性问题进行拟合,并基于R2R^2R2决定系数...

楚江客的记录 1万+

Uncaught SyntaxError: await is only valid in async functions...,以及async的就近原则

当你遇到这个问题时:Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules。 你就要去看一下你的await关键字是否放在async声明的函数里面,正确写法如下: async function insideFn() { await promiseFn() console.log('第二步执行完毕') } async的就近原则 有时候我们在async声明.

WanweI897的博客 1万+

手把手教你用C#实现TwinCAT 3 ADS通讯(附完整代码示例)

本文详细解析了如何使用C#实现TwinCAT 3 ADS通讯,包括协议核心价值、开发环境配置、变量通信实践及高级应用场景。通过完整代码示例和性能优化技巧,帮助开发者高效实现工业自动化系统中的实时数据交换,特别适合倍福(Beckhoff)平台用户。

weixin_29230901的博客 117

用户存续期价值评估CLV(三) Gamma-Gamma模型 Python模拟

Gamma-Gamma模型 前面已经提到过,Pareto/NBD和BG/NBD模型只对客户存续时间和交易次数进行建模,并不涉及客户未来交易所带来的现金价值。 Gamma-Gamma模型就是对这个问题的一个扩展解决方案。 Gamma-Gamma模型做了如下假设: 从客户角度上来说,交易金额在每个客户的平均交易价值上随机波动。(这一点并不是很有说服力) 所观察到的交易价值均值是隐含价值均值 ????(????) 的非完美计量 交易价值均值在客户中是变化的,即使这个值是稳定的(这个假设非常大) 在客户中的平

weixin_43171270的博客 4367

async导致函数结果出乎意料,改变原来代码的意图;await is only valid in async functions and the top level bodies of modules

await is only valid in async functions and the top level bodies of modules; async函数值返回值接收

qq_45327886的博客 1万+

FunASR与FreeSWITCH融合实战:从零构建高精度语音质检系统

本文详细介绍了如何将FunASR与FreeSWITCH融合,构建高精度语音质检系统。通过实时语音听写技术,结合热词定制和多模型切换,实现客服中心等场景的自动化质检,显著提升识别准确率和效率。系统架构涵盖音频采集、识别处理和业务应用三层,支持负载均衡和性能优化,适用于工业级部署。

weixin_29198045的博客 980

async await详解 & Promise

async await详解

pscool的博客 785

用Zotero+B站Kimi,我如何把一篇顶会论文快速做成组会PPT(含完整提示词)

本文介绍如何利用Zotero和Kimi快速将顶会论文转化为组会PPT,提升学术汇报效率。通过Zotero的文献管理插件和Kimi的AI提炼技术,实现从论文阅读到PPT生成的全流程自动化,帮助研究者在90分钟内完成高质量汇报准备。

weixin_30955617的博客 499

笔试题-2023-芯原-数字前端设计or验证【纯净题目版】

笔试题-2023-芯原-数字前端设计or验证【纯净题目版】

w0shishabi的博客 5685

掌握Promise和async/await编写优雅的异步代码

对于任何重要的网页应用来说,能够高效地处理异步操作是非常关键的。异步编程不仅可以避免网站卡顿,也可以大幅提升用户体验。JavaScript语言中处理异步最常见的方式就是Promise和async/await。它们都可以帮助我们优雅地编写非阻塞、异步代码。本文将详细介绍Promise的用法,以及async/await如何帮助我们解决"回调地狱"问题。通过学习这些知识,你可以在项目中使用它们编写出更简洁、合理的异步代码。​回调函数(callback)是一种常见的JavaScript编码模式。

爱蹦跶的全栈大A阿 2104

Flink Web UI 如何使用和调试保姆级教程(持续更新)

Running Jobs(运行中的作业):显示正在运行的所有 Flink 作业的列表。每个作业都有一个独特的 Job ID,可以点击进入查看作业的详细信息。Completed Jobs(已完成的作业):显示已经完成或取消的作业列表。:显示当前集群中所有 TaskManager 的健康状态,包括 CPU 使用率、内存使用情况、Slot 数量等。Job Manager Configuration(JobManager 配置):显示 JobManager 的一些配置参数,帮助调试和优化 Flink 集群。

大模型大数据攻城狮的专栏 3987

轻松掌握 Async/Await:让异步代码像同步代码一样优雅

Async/Await 是 ES2017 引入的语法糖,让异步代码看起来像同步代码一样简洁。Async/Await 的核心价值在于:提升异步代码的可读性、简化错误处理流程、保持与 Promise 的兼容性。

2403_84691304的博客 645

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Vue中的async/await:让异步代码更优雅

本文详细介绍了在Vue开发中使用async/await处理异步操作的最佳实践。首先讲解了async/await的基础概念,包括async函数和await表达式的作用。然后重点演示了在Vue组件中的具体应用场景:methods方法、生命周期钩子、计算属性结合watch的使用方式。文章还涵盖了与Vuex的结合使用、错误处理策略以及性能优化技巧,如并行执行、批量处理和竞态条件避免等。最后提供了实战技巧,包括可取消的异步操作和骨架屏实现。全文旨在帮助开发者用更优雅的方式编写异步代码,提升Vue应用的可维护性和用户体

承蒙关照! 936

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

鸿蒙异步并发 async/await 最佳实践,代码瞬间优雅

摘要:本文介绍了如何在鸿蒙ArkTS中使用async/await优化异步代码,避免回调地狱问题。通过三个实战场景演示:1)串行执行(登录后获取用户信息);2)并发执行(同时获取配置和广告);3)异常处理(捕获网络错误)。核心方法是使用async标记异步函数,await暂停执行直到Promise完成,使异步代码逻辑更清晰。文中提供了完整可运行的示例代码,帮助开发者用同步风格编写异步程序,提升代码可读性和维护性。

威哥爱编程,华为 HDE,鸿蒙极客、优快云博客专家、《鸿蒙 HarmonyOS 5/6 开发之路》系列图书第一作者 901

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

小白也能懂:用 async-await 写出优雅异步代码(附实战技巧)

return b;});只要对象带then});// 瞬间现代化。

一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身"农奴"把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟! 900

【前端开发必看】:掌握这6种async/await高级模式,写出更优雅的异步代码

掌握JavaScript async/await 技巧,轻松应对复杂异步流程。涵盖并发控制、错误处理、循环优化等6种高级模式,提升代码可读性与健壮性。前端开发效率飞跃,值得收藏。

FastSolve的博客 1073

async、await详解

一、async/await是什么? 简而言之, async用于申明一个function是异步的; 而await则可以认为是 async await的简写形式,是等待一个异步方法执行完成的。 二、async和await的基础使用 async/awiat的使用规则: async 表示这是一个async函数, await只能用在async函数里面,不能单独使用 async 返回的是一个Promise对象,await就是等待这个promise的返回结果后,再继续执行 await 等待的是一个Promise对象

Zheng_xinle的博客 8万+

别再只用async/await了!Promise.resolve() 这5个隐藏用法,让你的异步代码更优雅

本文深入探讨Promise.resolve()在JavaScript异步编程中的五大高阶用法,包括异步流程控制、混合数组处理、可测试代码模拟、前端状态管理和超时控制。通过实际代码示例,展示如何利用Promise.resolve()使异步代码更简洁健壮,提升开发效率和代码可维护性。

weixin_29006701的博客 207

vue中使用async和await来实现同步和异步【转载】

现在我们看看代码的执行过程,调用test函数时,它遇到了里面的await关键字,await代表等待,代码到这里会暂停,它在等什么呢,等待后面的promise对象执行完成,然后拿到promise的返回值,拿到返回值之后它继续往下执行,直到console.log()执行。先说一下async的语法,它作为一个关键字放在函数前面,用于表示函数是一个异步函数,因为async就是异步的异步,异步函数也就是意味着这个函数的执行不会阻塞后面代码的执行。语法很简单,就是在函数前面加上async,他就成异步函数啦。

babySan 2341

什么是async、await?

async “异步”的意思,async用于声明一个函数是异步的 await “等待”的意思,await用于等待异步完成,await只能在async函数中进行使用 通常async、await 都是跟随Promise一起使用的。 async返回的都是一个Promise对象同时async适用于任何类型的函数上。这样await得到的就是一个Promise对象(如果不是Promise对象的话那async返回...

H_c_l的博客 1322

JavaScript中异步函数async、await

async关键字用于声明一个异步函数:async异步函数和普通函数一样可以有很多中写法: 异步函数返回值 异步函数的内部代码执行过程和普通的函数是一致的,默认情况下也是会被同步执行。异步函数有返回值时,和普通函数会有区别(异步函数返回的是一个Promise):情况一:异步函数有普通的返回值时,异步函数的返回值相当于被包裹到Promise.resolve中; 情况二:如果我们的异步函数的返回值是Promise,状态由会由Promise决定; 情况三:如果我们的异步函数的返回值是一个对象并且实现了the

m0_71485750的博客 2098

ES7 - async/await处理异步

当我还在使用promise来发送异步请求的时候,部门前端大佬已经改用async/ await了,代码很简洁,同时async/await 已经被标准化,是时候学习一下了~ 一、async函数介绍 async 是 ES7 才有的与异步操作有关的关键字,和 Promise,Generator 有很大关联的。 【1】特点: 1、建立在 promise 之上。所以,不能把它和回调函...

越努力,越幸运! 757
上一篇: JavaScript预解析的一些理解
下一篇: 关于JS你不得不知道的几个小算法。(-)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值