百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

还在用老旧的Promise?你该试试Async/Await了!

liuian 2025-03-25 15:21 21 浏览

async函数,也就是我们常说的async/await,是在ES8中引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法。async和await关键字让使用 Promises变得容易,而无需刻意地链式调用Promise。并且与嵌套的.then相比,代码可读性更好。下面就来介绍一下它的具体使用以及规则。

一、async函数

1. 用法

在函数声明的前面加上async关键字,就变成了 async 函数。

async function f() {

return 'hello world';

}

2. 返回值

async 函数的返回值是一个 Promise 实例,Promise 实例的结果由 async 函数的返回值决定:

如果返回的是一个 Promise 实例,最终得到的 Promise 对象的状态与值与返回的 Promise 实例保持一致。

如果返回的是一个非 Promise 实例的值,async 函数返回的一个状态为 resolved 的 Promise 实例,value 是函数内返回的值。

如果没有返回值,async 函数返回一个状态为resolved 的 Promise 实例,value 是undefined。

如果抛出错误,async 函数返回一个状态为 rejected 的 Promise 实例,reason 是抛出的错误。

二、await表达式

async function main(){

let result = await Promise.resolve('hello world');

console.log(result); // hello world

};

main();

async function f(){

let result = await 998;

console.log(result); // 998

}

f();

async function foo(){

let result = await {

then(resolve, reject){

setTimeout(() => {

resolve('success')

}, 2000);

}

};

console.log(result); // success

}

foo();

1. 规则

await 表达式必须写在 async 函数的里面。但async函数中可以没有 await,不过一般二者是一起使用的。

await 表达式可以取到 Promise 实例的结果(就是状态发生改变后传到回调函数的值)。当然,必须等到 Promise 实例的状态发生变化,await 表达式才能取到值。

2. 关于 await 的右侧的表达式

一般为 Promise 实例,await 表达式的值就是该 Promise 实例的结果。

如果是个其他类型的值(非 Promise 类型),await 表达式的值就是这个值。

后面是一个 thenable 对象(即定义then方法的对象),那么会将其等同于 Promise 对象。(介绍 Promise.resolve() 方法的时候介绍过 thenable 对象)。

3. 注意

如果 await 右侧是个状态为失败的 Promise 实例,会抛出异常。我们建议将 await 表达式放在try...catch结构里面。

async function f() {

try {

await Promise.reject('出错了');

} catch(e) {

}

return await Promise.resolve('hello world');

三、案例

使用async/await有诸多好处,这里例举一个前端最常用的东西(ajax发送请求)来直观的感受一下使用async/await带来的便捷之处。

1. 传统的Ajax请求

//创建异步对象

var xhr = new XMLHttpRequest();

//设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端

xhr.open('GET','http://www.atguigu.com');

//注册事件 onreadystatechange 状态改变就会调用

xhr.onreadystatechange = function () {

//如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的

if (xhr.readyState == 4 && xhr.status == 200) {

    console.log(ajax.responseText); //输出相应的内容

  }

}

//发送请求

ajax.send();

2. 用promise封装Ajax

使用promise可以更方便管理异步请求。promise可以用在单个或多个ajax请求,在多个请求当中可以指定请求的顺序。话不多说,上代码:

function sendAjax(url) {

let xhr = new XMLHttpRequest()

return new Promise(function (resolve, reject) {

xhr.open('GET', url)

xhr.onreadystatechange = function () {

if (xhr.readyState === 4) {

if (xhr.status === 200) {

resolve(xhr.responseText) // 成功执行 resolve

} else {

reject() // 失败执行 reject

}

}

}

xhr.send()

})

}

let p1 = sendAjax('http://www.atguigu.com')

p1.then(function (data) {

console.log('成功了')

console.log(data)

}, function () {

console.log('失败了')

})

let p2 = sendAjax('http://www.atguigu.com')

p2.then(function (data) {

console.log('成功了')

console.log(data)

}, function () {

console.log('失败了')

})

3. async/await

使用async/await可以处理promise链式调用过长问题,async/await可以让我们同步书写请求嵌套,看起来更舒服:

// 假设有这么一个情况:

// 现有一个A请求,然后B请求依赖A请求返回的数据,C请求依赖B请求返回的数据...

// 如果是promise写

post('A', data)

.then(res1 => post('B', res1))

.then(res2 => post('C', res2))

.then(res3 => post('D', res3))

.then(res4 => post('E', res4))

...

// 换成async/await写

async handler() {

let a = await post('A', data)

let b = await post('B', a)

let c = await post('C', b)

let d = await post('D', c)

...

}

总结

async/await 可以直接拿到 Promise 的结果,可以代替 then() 方法和回调函数。可以取代链式调用,是回调地狱的终极解决方案。缺点是状态为 rejected 的 Promise 实例,会抛出异常,所以需要写在 try...catch结构中防止出错。

相关推荐

面试问了解Linux内存管理吗?10张图给你安排的明明白白!

来源:https://www.cnblogs.com/NanoDragon/p/12736887.html今天来带大家研究一下Linux内存管理。对于精通CURD的业务同学,内存管理好像离我们很远...

Linux Kernel 6.12震撼发布:实时性能飙升,开启全新计算时代!

概述LinusTorvalds在邮件列表中宣布推出LinuxKernel6.12,该版本带来了多项重要的更新和功能增强。更新亮点PREEMPT_RT支持主要内容:LinuxKernel...

linux Grub2功能、常见配置及使用方式

Grub2(GrandUnifiedBootloaderversion2)是一款功能强大的引导加载程序,提供了以下功能和常见配置:多操作系统支持:Grub2可以加载和引导多个操作系统,包括不同...

Linux内核必备知识点-platform总线详解

platform总线是学习linux驱动必须要掌握的一个知识点。本文参考已发布:Linux3.14内核一、概念嵌入式系统中有很多的物理总线:I2c、SPI、USB、uart、PCIE、APB、AHB...

linux kernel内核的头文件获取、安装等方法

交叉编译时经常会用到这些头文件。下载合适版本的linux地址:https://mirrors.aliyun.com/linux-kernel/https://mirrors.edge.kernel.o...

600个常用 Linux 命令,收藏备用!

本文为Linux命令大全,从A到Z都有总结,建议大家收藏以便查用,或者查漏补缺!A命令描述access用于检查调用程序是否可以访问指定的文件,用于检查文件是否存在accton用于打开或关闭记帐进程或...

Linux 中 `/proc/cpuinfo`文件中最常见的标志

/proc/cpuinfo是一个虚拟文件系统,在Linux系统中提供有关CPU(中央处理器)的信息。通过读取该文件,您可以获取有关处理器的详细信息,如型号、频率、核心数、缓存大小等。本文将介绍...

600个Linux命令大全,从A到Z,2023年收藏大吉!

本文为Linux命令大全(有PDF),从A到Z都有总结,建议大家收藏以便查用,或者查漏补缺!A命令描述access用于检查调用程序是否可以访问指定的文件,用于检查文件是否存在accton用于打开或关闭...

Linux下如何查看硬件信息?

我们在Linux下进行开发时,有时也需要知道当前的硬件信息,比如:CPU几核?使用情况?内存大小及使用情况?USB设备是否被识别?等等类似此类问题。下面良许介绍一些常用的硬件查看命令。lshwls...

从PXE到GRUB到VHD文件启动

今天玩点花活儿,之前的文章再探从VHD文件中启动Windows及Grub双启动VHD文件+TinyCoreLinux中研了一下GRUB和VHD文件的关联应用,那么结合PXE又会是怎么样的呢?...

bootra1n教学:Windows用户用U盘Linux实现checkra1n越狱方法

checkra1n越狱工具在前几天推出Linux版本,相信对于Windows用户可能也看得很模糊,甚至要切割硬碟到安装Linux系统太过于繁杂,这篇要来教大家最简易最快速利用U盘Linux...

不了解NUMA,就看不懂Linux内核

哈喽,我是子牙,一个很卷的硬核男人深入研究计算机底层、Windows内核、Linux内核、Hotspot源码……聚焦做那些大家想学没地方学的课程。为了保证课程质量及教学效果,一年磨一剑,三年先后做了这...

Linus Torvalds接受微软Hyper-V升级 下一代Linux启动会更快

虽然Windows的粉丝和Linux的粉丝经常喜欢进行激烈的键盘大战,但操作系统的制造商们自己也了解彼此的优缺点。毫无疑问,微软也明白这一点,事实上,它甚至鼓励用户尝试Linux,尽管是使用...

deepin使用笔记——开机卡LOGO,无法正常关机的解决办法

第一次使用deepin操作系统,很容易遇到几种情况:1,开机卡LOGO,无法进入系统。2,开机可以进入系统,但是进入系统后桌面环境无法正常打开,一直卡着什么都不能用。3,开机后看似一切正常,但关机的时...

如何检查Linux系统硬件信息?从CPU到显卡,一网打尽!

你可能会问:“我为什么要关心硬件信息?”答案很简单:硬件是Linux系统的根基,了解它可以帮你解决很多实际问题。比如:性能调优:知道CPU核心数和内存大小,才能更好地调整程序运行参数。故障排查:系统卡...