一、如何使用async/await
async函数是Generator的一个语法糖,使用async函数实际上返回的是一个Promise对象。如下:
async function fn(){
return 30;
}
// 或者
const fn = async () =>{
return 30;
}复制代码
在声明函数的时候,前面加上关键字async
即可。我们可以使用 console.log
打印出上边声明的函数fn,结果如下:
console.log(fn());
// result
Promise = {
_proto_: Promise,
[[PromiseStatus]]: "resolved",
[[PromiseValue]]: 30
}复制代码
显然,fn的运行结果其实就是一个Promise对象,因此我们可以使用then来处理后续逻辑。
fn().then(res =>{
console.log(res);
})复制代码
await的是含义是等待。意思是代码需要等待await后面的函数运行完成并且有了返回结果之后,才继续执行后续的代码,以此来实现同步的效果。 需要注意的是,await
关键字只能在async
函数中使用,并且await
后面的函数运行后必须返回一个Promise
对象才能实现同步的效果。
当我们使用一个变量去接收await的返回值时,该返回值是Promise中resolve出来的值(也就是PromiseValue)。
// 定一个返回Promise对象的函数
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(1);
},1000);
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(2);
},1000);
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(3);
},1000);
})
}
const foo = async () =>{
const result_1 = await f1();
console.log(result_1);
const result_2 = await f2();
console.log(result_2);
const c = await f3();
console.log(result_3);
}
foo();
// 运行结果:
// 1
// 2
// 3复制代码
运行这个例子我们可以看出,当在async
函数中,运行遇到await
时,就会等待await
后面的函数运行完毕,而不会直接执行后续程序
二、async/await相对于直接使用Promise的优势
如果我们直接使用Promise的话,想要实现以上的结果,就不得不把后续的逻辑写在then方法中。
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(1);
},1000);
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(2);
},1000);
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(3);
},1000);
})
}
const foo = () =>{
return f1().then(t =>{
console.log(t);
return f2();
}).then(t =>{
console.log(t);
return f3();
}).then(t =>{
console.log(t)
});
}
foo();复制代码
异常处理
在Promise中,我们知道是通过catch的方式来捕获异常。而当我们使用async时,则是通过try/catch
来捕获异常。
function fn(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("some error.");
},1000)
})
}
const foo = asyn () =>{
try{
await fn();
}catch(e){
console.log(e); //some error.
}
}
foo();复制代码
如果有多个await函数,那么只会返回第一个捕获到的异常。
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f1 error");
},1000)
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f2 error");
},1000)
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f3 error");
},1000)
})
}
const foo = async () =>{
try{
await f1();
await f2();
await f3();
}catch(e){
console.log(e); //f1 error
}
}
foo();复制代码
如果我们直接使用Promise,实现以上效果,代码应该写成如下:
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f1 error");
},1000)
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f2 error");
},1000)
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f3 error");
},1000)
})
}
const foo = () =>{
return f1().then(() =>{
return f2();
}).then(() =>{
return f3();
}).catch(err =>{
console.log(err);
})
}
foo();复制代码
很显然,如果使用async/await的话,代码结构会更加简洁,逻辑也更加清晰,更利于项目中的开发以及维护。