async函数
被称为JavaScript异步编程的最终解决方案。
基本用法
async声明函数内部有异步操作,且该函数返回一个Promise对象,可以进行和promise相关的所有操作。
await关键字必须在async函数内部调用。表示等待异步操作完成,再接着执行函数体内接下来的语句。
async函数的多种声明形式:
// 普通函数声明
async function wlk1(){};
// 函数表达式
const wlk2 = async function(){};
// 作为对象的方法
let obj = {
async wlk3(){};
}
obj.wlk3().then(...);
// 作为Class的方法
class Space{
constructor() {}
async wlk4(){}
}
// 箭头函数
const wlk5 = async ()=>{};async
声明一个函数为异步函数,且该函数返回一个Promise对象。
async函数内部return语句返回的值,会成为then方法回调函数的参数。
async function f(){
return "hello async!";
}
f().then(console.log);
// hello async!async函数内部所有的await等待的结果返回后,才会执行then回调。如下:
async function f() {
let res1 = await getFile1();
let res2 = await getFile2();
let res3 = await getFile3();
return "all files got!";
}
f().then(console.log);await
正常情况下,await命令后面等待的是一个Promise对象的结果(resolve或reject传递出来的值)。如果不是Promise对象结果,就直接返回对应的值。如下:
async function f(){
return await "hello await!" // 等同于 return "hello await!"
}
f().then(console.log);
// hello await!async函数内部如果有一个promise对象变成reject状态,则该async函数会中断执行,立即返回,后面的代码不会被执行。如下:
async function f() {
let res = await Promise.reject('出错了');
let res2 = await 123; // 不会被执行
console.log(res,res2);// 不会被执行
}
f().catch(console.log);
// 出错了如果希望一个async函数失败了,后面的async函数继续执行。可使用try...catch结构。如下:
async function f() {
try{
await Promise.reject('出错了');
}catch(e){
console.log(e)
}
return await Promise.resolve(111);
}
f().then(console.log);
// 出错了
// 111注意以上代码的return关键字,必须存在,否则then回调函数的参数会为undefined。而reject时可以在不用return关键字。
提示
reject相当于throw一个Error,catch语句就是模拟的try...catch的catch语句块。
async function f() {
await Promise.resolve('没出错'); // 加入 return 关键字才会打印出值
}
f().then(console.log);
// undefined
async function f() {
await Promise.reject('出错了');
}
f().catch(e => console.log(e))
// 出错了使用注意点
第一点: await命令后面等待的是一个Promise对象的结果,状态有可能变为rejected,所以最好把await命令放在try...catch代码块中。
async function f() {
try{
let res = await promiseResult();
}catch (e) {
console.log(e);
}
}
// 另一种写法
async function f1() {
let res = await promiseResult().catch(console.log);
}警告
如果await后面等待的结果rejected,以上代码中的res就不会得到返回值,会为undefined。这点需要特别注意。
第二点: 多个await命令后面的异步操作,如果不存在继发关系,最好让他们同时触发。
不推荐的写法:
let func1 = await getName();
let func2 = await getAge();
//以上两个异步操作是独立的,互不依赖,如果这样写成继发关系,会比较耗时。推荐写法(同时触发):
// 写法一 : 利用 Promise.all()。
let [func1,func2] = await Promise.all([getName(),getAge()]);
// 写法二 : 利用 await 等待已执行函数结果
let func1Res = getName();
let func2Res = getAge();
let func1 = await func1Res;
let func2 = await func2Res;第三点: await命令只能用在async函数中,如果用在普通函数中,会报错。
wanglongkai's notes