优雅的async/await
1、概述
大家好,我是欧阳方超。
本次看一下async/await的使用。
2、async/await
async/await是基于Promise的,可以说是Promise的语法糖。
2.1、async关键字
async关键字一般会放在函数前面,这会使得函数返回一个Promise对象:
async function testFunction() {
return "async";
}
这等效于下面的代码:
function testFunction() {
return Promise.resolve("async");
}
调用上面的两个testFunction()函数都会返回Promise对象,接着就能使用Promise的相关函数了:
function testFunction() {
return Promise.resolve("async");
}
testFunction().then((value)=>{console.log(value)});
可以看出在我们不写任何关于Promise的内容时,async关键字已经帮我们返回了Promise对象;与async搭配使用的还有一个关键字——await,它可以帮助我们在不使用then()函数时也能达到同样的目的。
2.2、await关键字
await关键字只能用在async函数内部或JavaScript模块中。其语法如下:
let value = await expression;
其中expression一般是一个Promise对象,或是其他任何需要等待的值。
await运行机制
await关键字会导致async函数暂停执行,直到Promise对象变为settled状态(包括fulfilled或rejected),async函数才会恢复执行;当恢复执行时,await expression 的值是状态为fulfilled的Promise对象的value值,如果Promise对象的状态为rejected,await表达式会把异常原因抛出。
Promise对象状态为fulfilled的示例:
async function testFunction() {
let promise = new Promise((resolve, reject)=>{
setTimeout(()=>{resolve("ok")}, 3000);
});
let res = await promise;
console.log(res);
}
testFunction();
上面示例中,调用testFunction()后,程序执行到await promise这一行时,会“暂停”不在往下执行,一直等到3秒后,resolve()被调用了,Promise对象的状态变为fulfilled,res变量才会拿到调用resolve()函数时传入的参数。注意,这种暂停只是发生在testFunction()函数内部,并不影响函数外其他代码的执行,毕竟testFunction()是一个async function,它不会阻塞其他任务。
Promise对象状态为rejected的示例:
async function testFunction() {
try {
let promise = new Promise((resolve, reject)=>{
setTimeout(()=>{reject(new Error("异常"))}, 3000);
});
let res = await promise;
console.log("本行不再执行");
} catch (err) {
console.log(err);
}
}
testFunction();
console中的执行结果:
上面示例中,promise对象的状态因调用了reject()而变成了rejected,当执行到await promise时,异常原因会被抛出,被catch捕获到,在try中,当异常发生时,出现在发生异常之后的代码都不会得到执行。
await后不是Promise对象
如果await关键字后跟的表达式的值不是一个Promise对象,则返回该值本身,如下:
async function testFunction() {
let promise = await 20;
console.log(promise);
}
testFunction();
3、总结
async关键字在函数前面有两个作用:
- 让这个函数始终返回一个Promise对象;
- 可以在函数内使用await关键字;
promise前的await关键字使得JavaScript暂停async函数中下面代码的执行,一直等待promise状态变为settled,之后: - 如果是一个错误,会产生异常——就像那里调用了throw error一样;
- 否则就返回正常结果。
async/await关键字为编写易于读写的异步代码提供了较好的方式,我们可以几乎不再使用promise.then/catch方法,但是我们应该始终牢记这两个关键字时基于promise的,有些场景下还是需要使用的;另外当需要同时等待多个任务时,使用Promise.all不失为一个好办法。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。