定义
async/await 是 Js 中的语法糖,基于Promise实现,它不能用于普通的回调函数。它在语法上更像同步代码,使得异步代码的编写更加简洁易懂。
async:
- 关键字用于定义一个异步函数,表明函数里面可能有异步过程(函数内含有await则代表有异步)。
- async是非阻塞的。async函数里面如果有异步过程会等待,但是async函数本身会马上返回,不会阻塞当前线程,即async外部代码不等待会继续执行。
- async函数返回类型为Promise对象
返回值写法不做要求,在async函数中无论返回什么,最终都会被处理成promise对象。
return new Promise() 不做处理
return str async会把返回值通过Promise.resolve() 封装成 Promise 对象
无返回值 async将处理成 Promise.resolve(undefined); - 执行async函数时,写法无特殊要求,将其当作普通函数即可。若要取得async函数的返回对象,则需要加上.then()来获取。
fn.then((res) => {
// res即为 fn(async函数)中的return值
console.log(res)
})
awiat:
- await只能在async函数内部使用
- await关键字后面是一个Promise对象
(也可以写同步代码,但是程序会自动将其转换成promise对象,与直接去掉await效果一致,无意义) - await后面是promise对象时,将会等待这个对象resolve值,作为结果。若promise对象变为reject,那么整个async都会被中断
运用场景
一、等待一个或多个异步函数(请求)完成后再执行后续程序,无需获取异步函数返回值
async
以下三种fn1()函数写法,均会等待await后接函数执行完成后,再执行await下面剩余的代码
- 写法一(最简洁):
async fn1() {
await fn2();
await fn3();
}
- 写法二(在typescript中):
async fn1(): Promise<void> {
await fn2();
await fn3();
}
- 写法三:
fn1() {
return new Promise(async (resolve, reject) => {
await fn2();
await fn3();
if(true) {
resolve(true);
}
}
}
console.log(fn1()) // 得到的是resolve的值
await
await后面接promise时,必须resolve(),否则程序会一直等待
- 写法一(后面直接跟一个异步函数名称):
async fn1() {
await fn2();
await fn3();
}
// 已将请求封装为promise对象,此处可直接返回
fn2() {
return this.testService.apiName(token).then((result) => {
console.log(11);
}).catch((error) => {
console.log(22);
});
}
fn3() {
return new Promise((resolve, reject) => {
this.testService.apiName(token).then((result) => {
resolve(true);
}).catch((error) => {
reject(false);
});
}
}
- 写法二(直接跟异步操作):
async fn1() {
await this.testService.apiName(token).then((result) => {
console.log(11);
}).catch((error) => {
console.log(22);
});
}
- 写法三(后跟new promise()):
async fn1() {
await new Promise((resolve, reject) => {
this.testService.apiName(token).then((result) => {
resolve(true);
}).catch((error) => {
reject(false);
});
}
}
二、需等待一个或多个请求(异步操作)完成后,获取返回的值,在进行后续操作
async fn1() {
const str1 = await fn2();
const str2 = await fn3();
const str3 = await fn4(str1);
// 这里的str1、str2、str3 是promise中resolve的值
const str4 = str1 + str2 +str3;
}
fn2() {
return new Promise((resolve, reject) => {
this.testService.apiName(token).then((result) => {
resolve(1);
}).catch((error) => {
reject(false);
});
}
}
fn3() {
return new Promise((resolve, reject) => {
this.testService.apiName(token).then((result) => {
resolve(2);
}).catch((error) => {
reject(false);
});
}
}
fn4(str) {
return new Promise((resolve, reject) => {
this.testService.apiName(token,str).then((result) => {
resolve(3);
}).catch((error) => {
reject(false);
});
}
}
在上面代码中,fn2,fn3,fn4按顺序执行。因此可以在后续异步中(fn4方法)使用前面异步返回的值。
经常实际运用于:需要等待一个请求完成后,拿到返回的值,再用此返回值作为参数发起下一个请求。
三、等待async执行完毕后,在执行某操作
因为async返回的实际是一个promise,可以通过 .then 拿到返回值
async fn1() {
const str1 = await fn2();
const str2 = await fn3();
return str1 + str2;
}
fn1().then(val => {
// val值为 str1 + str2
console.log(val)
})
console.log('我会先执行')
注意:当await 后接的Promise 对象抛出异常,即 reject(), 需要用try…catch…捕获异常
- 写法一:
async fn1() {
try {
await fn2();
} catch (err) {
// 此处会打印出22,即fn2中的promise对象reject的值
console.log(err);
}
}
- 写法二:
async fn1() {
await fn2().catch(function (err){
// 打印出22
console.log(err);
});
}
fn2() {
return new Promise((resolve, reject) => {
this.testService.apiName(token).then((result) => {
reject(22);
});
}
}