JavaScript 中的 async/await 是 AsyncFunction 特性 中的关键字,从字面意思来理解:async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。
先简单介绍一下async/await。
另外还有一个很有意思的语法规定,await 只能出现在 async 函数中。然后细心的朋友会产生一个疑问,如果 await 只能出现在 async 函数中,那这个 async 函数应该怎么调用?
async function testAsync() {
return "hello async";
}
const result = testAsync();
console.log(result);
输出结果: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello async"}
可以看出:async 函数返回的是一个 Promise 对象。 如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。
如果没有返回值:
async function testAsync1() {
console.log("hello async");
}
let result1 = testAsync1();
console.log(result1);
输出结果: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
结果返回Promise.resolve(undefined)。
所以在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且不会阻塞后面的语句。这和普通返回 Promise 对象的函数并无二致。
那么下一个关键点就在于 await 关键字了。
一般来说,都认为 await 是在等待一个 async 函数完成。准确说,await 等待的是一个表达式,这个表达式的 是 Promise 对象或者其它值 。
因为 async 函数返回一个 Promise 对象,所以 await 可以用于等待一个 async 函数的返回值——这也可以说是 await 在等 async 函数,但要清楚,它等的实际是一个返回值 ,await 后面实际是可以接普通函数调用或者直接量的。
await 等到了它要等的东西,一个 Promise 对象,或者其它值,然后呢?await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西。
如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。这就是 await 必须用在 async 函数中的原因。async 函数调用不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行。
看一个简单的例子:
function testSome () {
console.log("执行testSome ");
return "testSome ";
}
async function testAsync() {
console.log("执行testAsync");
return Promise.resolve("hello async");
}
async function test() {
console.log("test start...");
const v1 = await testSometing(); //关键点1
console.log(v1);
const v2 = await testAsync();
console.log(v2);
}
test();
var promise = new Promise((resolve)=> {
console.log("promise start..");
resolve("promise"); //关键点2
});
promise.then((val)=> console.log(val));
console.log("test end...")
输出结果:
test start...
执行testSome
promise start..
test end...
testSome
执行testAsync
promise
hello async
const v1 = await testSometing();
会先执行testSome这个函数,打印出“执行testSome”的字符串
var promise = new Promise((resolve)=> {
console.log("promise start..");
resolve("promise"); //关键点2
});
然后打印出“promise start…”接下来会把返回的这promise放入promise队列,
test end...,
testSome
执行testAsync
promise
hello async
这个就是在async/await 函数之后js的执行顺序
来一个例子比较一下then()链和async/awai:
执行三个步骤,每一个步骤都需要之前步骤的结果。
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);
}
1.先用 .then()的方法
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();
看起来就非常复杂!一堆的参数处理,还非常容易在逻辑上出错。
2.用 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();
这样逻辑就非常清晰了,浅显易懂,还便于维护!
借鉴博客:https://www.cnblogs.com/lpggo/p/8127604.html