async/await其实是Generator的语法糖,它能实现的效果都能用then链来实现,它是为优化then链而开发出来的。从字面上来看,async是“异步”的简写,await是等待,所以很好理解async是用于声明异步的,而await用于等待一个异步方法执行完成。当然语法上强制规定await只能出现在asnyc函数中。
async function test(){
return 'hello world'
}
let res = test()
console.log(res)
async function test(){
return 'hello world'
}
let res = test()
console.log(res) //Promise对象
res.then(result => {
console.log(result) //hello world
})
async function test(){
return 'hello world'
}
let res = test()
console.log(res)
res.then(result => {
console.log(result)
})
console.log("aaa") //立即执行aaa
一般来说,都认为await是在等待一个async函数完成。不过按语法说明,await等待的是一个表达式,这个表达式的计算结果是Promise对象或者其他值。因为async函数返回一个Promise对象,所以await可以用于等待一个async函数的返回值——也可以说是await是在等async函数,但要清楚,它等的实际是一个返回值。注意到await不仅仅用于等Promise对象,它可以等任意表达式的结果,所以await后面实际是可以接普通函数调用或者直接量的。
function test1(){
return "test1"
}
async function test2(){
return "test2"
// return Promise.resolve("test2")
}
async function test3(){
const res1 = await test1() //不是Promise对象
const res2 = await test2() //Promise对象
console.log(res1,res2) //test1 test2
}
test3()
function test1(x){
return new Promise(resolve => {
setTimeout(() =>{
resolve(x)
},3000)
})
}
async function test2(){
let res = await test1('hello world')
console.log(res) //3s后输出hello world
console.log("aaa") //3s后输出aaa
}
test2()
console.log("bbb") //立即输出bbb
async function test(){
return Promise.reject('错误')
}
test().then(res => {
console.log("success:",res)
},err => {
console.log("error:",err)
})
//error:错误
async function test(){
try{
await new Promise(function(resolve,reject){
throw new Error('错误')
});
} catch(err){
console.log("error:",err)
}
return await('成功');
}
单一的 Promise 链并不能发现 async/await 的优势,但是,如果需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了(很有意思,Promise 通过 then 链来解决多层回调的问题,现在又用 async/await 来进一步优化它)。
假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。仍然用 setTimeout 来模拟异步操作:
/**
* 传入参数 n,表示这个函数执行的时间(毫秒)
* 执行的结果是 n + 200,这个值将用于下一步骤
*/
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return takeLongTime(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return takeLongTime(n);
}
现在用 Promise 方式来实现这三个步骤的处理:
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => step2(time2))
.then(time3 => step3(time3))
.then(result => {
console.log(`result is ${result}`);
console.timeEnd("doIt");
});
}
doIt();
// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1507.251ms
输出结果 result 是 step3() 的参数 700 + 200 = 900。doIt() 顺序执行了三个步骤,一共用了 300 + 500 + 700 = 1500 毫秒,和 console.time()/console.timeEnd() 计算的结果一致。
如果用 async/await 来实现呢,会是这样:
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time2);
const result = await step3(time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
结果和之前的 Promise 实现是一样的,但是这个代码看起来是不是清晰得多,几乎跟同步代码一样