ES8 中 async 与 await 使用方法详解

举报
SHQ5785 发表于 2024/03/16 14:43:52 2024/03/16
【摘要】 一、前言在前期博文中,针对异步编程,提出了Promise解决方案。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息,解决回调函数嵌套过多的情况。ES2017 标准引入了 async 函数,使得异步操作变得更加方便。async 是“异步”的简写,比如Ajax中就有这个,代表异步请求; 因为await只能出现在async函数中的语法规定,await 可以认为是 async w...

一、前言

前期博文中,针对异步编程,提出了Promise解决方案。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息,解决回调函数嵌套过多的情况。

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

async 是“异步”的简写,比如Ajax中就有这个,代表异步请求; 因为await只能出现在async函数中的语法规定,await 可以认为是 async wait 的简写。所以应该很好理解 async 用于声明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。

二、async 作用

async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。

async function testAsync() {
	return "Hello Async"
}

const result = testAsync();

console.log(result)

执行结果如下图所示:

在这里插入图片描述

很明显,async函数返回的就是promise对象。

那么在没有await配合下,async返回promise对象,所以可以配合then处理。

async function testAsync() {
	return "Hello Async"
}

testAsync().then(result => {
	console.log(result);
})

执行结果如下图:

在这里插入图片描述

返回同样结果,所以和promise对象中then用法一样的效果。回想一下 Promise 的特点——无等待,所以在没有 await 的情况下执行 async 函数,它会立即执行,并返回一个 Promise 对象,并且,绝不会阻塞后面的语句。这和普通返回 Promise 对象的函数并无二致。

三、await 作用

await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西。如果它等待的是一个 Promise 对象,等 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

注⚠️: async 函数调用不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行。

function takeLongTime() {
	return new Promise(resolve => {
		setTimeout(() => {"..模拟耗时操作.."}, 1000);
	});
}

takeLongTime().then(v => {
	console.log("promise:", v)
})

改用 async/await 形式如下:

function takeLongTime() {
	return new Promise(resolve => {
		setTimeout(() => {"..模拟耗时操作.."}, 1000);
	});
}

async function test() {
	const v = await takeLongTime();
	console.log(v);
}

test();

以上两段代码中,两种调用方式对异步调用的处理(实际就是对 Promise 对象的处理)差别并不明显,甚至使用 async/await 还需要多写一些代码,那它的优势到底在哪?

四、async/await 优势在于处理 then 链

单一 Promise 链并不能发现 async/await 的优势,但是,如果需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了(Promise 通过 then 链来解决多层回调的问题,现在又使用 async/await 来进一步优化它)。

假设一个业务流程,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。仍然用 setTimeout 来模拟异步操作:

function takeLongTime(n){ 
	return new Promise(resolve => {
		setTimeout(() => resolve(n + 200),n);
	}
);

function step1(n){
	console.log(`step1 with ${n}`); 
	return takeLongTime(n);
}

function step2(m, n){
	console.log(`step2 with ${m} and ${n}`); 
	return takeLongTime(m +n);
}

function step3(k, m, n) {
	console.log(`step3 with ${k}, ${m} and ${n}`); 
	return takeLongTime(k + m + n);
}

Promise 方式处理异步:

function doIt(){
	console.time("doIt"); 
	const time1 =300; 
	step1(time1) 
		.then(time2 => { 
			return step2(time1,time2) 
		.then(time3 => [time1,time2,time3]); 
	}) 
	.then(times => { 
		const [time1, time2,time3] = times; 
 		return step3(time1,time2,time3);
	}
	.then(result =>{ 
		console.log(`result is ${result}`); 
		console.timeEnd("doIt"); 
	}); 
} 
	
doIt(); 

在这里插入图片描述

async/await 方式处理异步:

async function doIt() {
	console.time("doIt"); 
	const time1 = 300; 
	const time2 = await step1(time1); 
	const time3 = await step2(time1,time2); 
	const result = await step3(time1, time2,time3); 
	console.log(`result is ${result}`); 
	console.timeEnd("doit"); 
} 

doIt(); 

在这里插入图片描述

优化效果显而易见!

五、拓展阅读

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。