async/await
作者:laihuamin
链接:https://juejin.im/post/5d9e8539f265da5b8a515e63
来源:掘金
前言
js有很多异步处理的解决方案,而async/await
就是其中的一种,最近有在学习和运用koa,在服务端中,很少用到promise,而是选择了更加优雅的async/await
。当然,一种新方案的出现,我们不光需要学会怎么写,也要学会他的原理。
async/await起到什么作用
async/await
从字面意思上很好理解,async是异步的意思,await有等待的意思,而两者的用法上也是如此。async用于申明一个function是异步的,而await 用于等待一个异步方法执行完成。
async
async的语法很简单,就是在函数开头加一个关键字,示例如下:
async function f() {
return 1;
}
async关键字的意思很简单,就是函数返回的是一个promise。
async function f() {
return 1;
}
f().then((res) => {
console.log(res)
}) // 1
async函数会返回一个promise对象,如果function中返回的是一个值,async直接会用Promise.resolve()
包裹一下返回。
await
关键词await是等待的意思,那么他在等什么呢? 在MDN上写的是:
[return_value] = await expression;
等的是一个表达式,那么表达式,可以是一个常量,变量,promise,函数等。
function getSomething() {
return "something";
}
async function testAsync() {
return Promise.resolve("hello async");
}
async function test() {
const v1 = await getSomething();
const v2 = await testAsync();
console.log(v1, v2);
}
test(); // something hello async
为什么await关键词只能在async函数中用
await操作符等的是一个返回的结果,那么如果是同步的情况,那就直接返回了。
那如果是异步的情况呢,异步的情况下,await会阻塞整一个流程,直到结果返回之后,才会继续下面的代码。
阻塞代码是一个很可怕的事情,而async函数,会被包在一个promise中,异步去执行。所以await只能在async函数中使用,如果在正常程序中使用,会造成整个程序阻塞,得不偿失。
async/await中错误处理
promise并不是只有一种resolve,还有一种reject的情况。而await只会等待一个结果,那么发生错误了该怎么处理呢?
用try-catch来做错误捕捉
async function myFunction() { try { await Promise.reject('1'); } catch (err) { console.log(err); } } myFunction(); // 1
用promise的catch来做错误捕捉
async function myFunction() { await Promise.reject('1').catch((err) => { console.log(err); }); } myFunction(); // 1
async/await和promise的区别
promise最大的问题就是在于业务复杂之后,then内部的逻辑也变得复杂,或者循环的异步嵌套场景等,会写出来不那么优美。
我随意列举一个嵌套的例子,然后分别用async/await
和promise,你就能感受到两者之间的差距:
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(m, n) {
console.log(`step2 with ${m} and ${n}`);
return takeLongTime(m + n);
}
function step3(k, m, n) {
console.log(`step3 with ${k}, ${m} and ${n}`);
return takeLongTime(k + m + n);
}
takeLongTime起到的作用就是延时之后给出延时的数据。
step1代表第一步延时了多久。
step2代表第一步和第二部总共延时了多久。
step3代表第一步、第二步和第三步一共延时了多久。
- promise版本
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => {
return step2(time1, time2)
.then(time3 => [time1, time2, time3]);
})
.then(times => {
const [time1, time2, time3] = times;
return step3(time1, time2, time3);
})
.then(result => {
console.log(`result is ${result}`);
console.timeEnd("doIt");
});
}
doIt();
- async/await版本
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time1, time2);
const result = await step3(time1, time2, time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
在这种复杂逻辑中,我们就能发现async/await
确实比then链有优势。
async/await是一种异步的解决方案,而koa中支持这一特性,所以,在基于koa来写服务端代码的时候,这种语法糖不可避免,学习和运用它是我们的必修课。
本文系作者 @Mr.Yang 原创发布在果皮皮站点。未经许可,禁止转载。
暂无评论数据