async和await的用法以及原理分析

在这里插入图片描述
大家好,这篇文章让我们来了解一下 async/await 语法糖的用法以及实现原理。

async/await 语法糖其实就是为了简化 promise.then 繁琐的链式调用而产生的,为了让代码更简洁,书写更方便。

一、async的用法以及功能点:

  1. async 函数的返回值是一个 promise 对象;
  2. 返回的 promise 对象的结果由 async 函数中的返回值决定,有三种情况:
    • 返回值是一个新的 promise 对象;
    • 返回值是非 promise 对象的任意值;
    • throw抛出错误;

上面的第2个功能点熟悉不?看过我之前写的 “手写promise原理系列” 篇章的小伙伴应该都知道,这里 async 函数中的返回值其实跟 promise.then 方法的返回值描述规则是一模一样的。

想了解更多,请回看 手写promise原理系列二:手写promise的关键逻辑梳理,promise用法原理 中的第四个知识点:promise.then() 返回的 promise 对象的结果由什么决定?

下面,让我们用代码来加深一下印象:

(1)async 函数内部无返回值。

async function asyncFn() {
    
     };
let p = asyncFn();
console.log(p);

在这里插入图片描述

(2)async 函数内部返回成功的 promise 对象以及失败的 promise 对象

async function asyncFnResolve() {
    
     
	return new Promise((resolve, reject) => {
    
    
		resolve("OK");
	});
};
async function asyncFnReject() {
    
     
	return new Promise((resolve, reject) => {
    
    
		reject("NO");
	});
};
let p1 = asyncFnResolve();
let p2 = asyncFnReject();
console.log(p1);
console.log(p2);

在这里插入图片描述

(3)async 函数内部返回一个普通值。

async function asyncFn() {
    
     
	return "111";
};
let p = asyncFn();
console.log(p);

在这里插入图片描述
(4)async 函数内部抛出异常,返回一个失败的 promise 对象。

async function asyncFn() {
    
     
	throw "error";
};
let p = asyncFn();
console.log(p);

在这里插入图片描述

二、await 的用法以及功能点:

  1. await 语法只能在 async 函数体中 或者 模块的顶级主体中使用,否则报错
  2. await 右侧的表达式一般为 promise 对象,但也可以是其他值;
  3. 如果 await 右侧是 promise 对象,则 await 返回的是 promise 成功的值
  4. 如果 await 后面跟随的 promise 对象失败了,则使用 try…catch… 语句捕获错误;
  5. 如果表达式是其他值,直接将此值作为 await 的返回值;
  6. async 函数中遇到 await 语句时会暂停执行,等待获取状态结果,await 语句后面的代码会放到微任务队列等待同步任务执行完毕之后再继续执行

(1)await 不在 async 函数中使用时报错

fn();
function fn(){
    
    
	await "111";
}

在这里插入图片描述
报错信息译文为:未捕获的语法错误:await仅在异步函数和模块的顶级主体中有效

那什么是模块的顶级主体呢?可以参考这篇文章 顶级 await 在 Node.js 模块中可用啦!

(2)await 后面跟普通值

asyncFn()
async function asyncFn(){
    
    
	let p = await "111";
	console.log(p);  // "111"
}

(3)await 后面跟成功的 promise 对象

asyncFn()
async function asyncFn(){
    
    
	let p = await new Promise((resolve, reject) => {
    
    
		resolve("111");
	});
	console.log(p); // "111"
}

(4)await 后面跟失败的 promise 对象

asyncFn()
async function asyncFn(){
    
    
	let p = await new Promise((resolve, reject) => {
    
    
		reject("NO");
	});
	console.log(p); // 报错
}

在这里插入图片描述

需要使用 try…catch… 捕获错误,如下:

asyncFn()
async function asyncFn(){
    
    
	try {
    
    
		await new Promise((resolve, reject) => {
    
    
			reject("NO");
		});
	} catch (err) {
    
    
		console.log(err); // "NO"
	}	
}

在这里插入图片描述

三、async/await的实用案例

比方说,我们要调用以下三个接口获取数据,如下:

let a = "https://www.baidu.com";
let b = "https://www.taobao.com";
let c = "https://www.jd.com";

使用 promise 方式:

let p = new Promise((resolve, reject) => {
    
    
	let data = fetch(a);
	resolve(data);
});
p.then(res1=> {
    
    
	console.log(res1);
	return new Promise((resolve, reject) => {
    
    
		let data = fetch(b);
		resolve(data);
	});
}).then(res2 => {
    
    
	console.log(res2);
	return new Promise((resolve, reject) => {
    
    
		let data = fetch(c);
		resolve(data);
	});
}).then(res3 => {
    
    
	console.log(res3);
})

上面代码中 fetch 调用接口本身返回的就是 promise 对象,代码示例中 fetch 外面又包了一层 promise 是为了演示 promise.then 链式调用的繁琐性,因为真实的项目中代码会更多,勿怪。

fetch 接口调用的返回值:

在这里插入图片描述

使用 async/await 方式:

getData();
async function getData(){
    
    
	let res1 = await fetch(a);
	console.log(res1);
	let res2 = await fetch(b);
	console.log(res2);
	let res3 = await fetch(c);
	console.log(res3);
}

上面的两种方式书写代码都是异步获取接口的返回值,但我就问你,async/await 的使用方式,简洁不简洁,优雅不优雅。

四、async/await的实现原理

请参考这篇文章:async/await原理揭秘

猜你喜欢

转载自blog.csdn.net/ThisEqualThis/article/details/129539043