参考博客:理解 JavaScript 的 async/await

async/await 是Generator的语法糖,异步编程更加直观且易于理解。

async/await 的优势在于处理 then 链。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//传入参数 n,表示这个函数执行的时间(毫秒)
//执行的结果是 n + 200,这个值将用于下一步骤

// async前缀的作用:使函数返回Promise
// 该函数的返回值已经是Promise,故不需要加async前缀

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();

// await后边加一个表达式
// 如果它等到的不是一个Promise对象,那await表达式的运算结果就是它等到的东西
// 如果它等到的是一个Promise对象,需要等待Promise对象resolve,然后得到resolve的值,作为await表达式的运算结果

// 如果Promise的状态为reject,使用try/catch来处理错误
async function doIt() {
try{
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1); // step1(time1)返回一个Promise,需拿到它resolve的值,再赋值给time2
const time3 = await step2(time2); // step2(time1)返回一个Promise,需拿到它resolve的值,再赋值给time3
const result = await step3(time3); // step3(time1)返回一个Promise,需拿到它resolve的值,再赋值给result
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
catch (err) {
console.error(err);
}
}

doIt();

/*
输出结果:
step1 with 300
step2 with 500
step3 with 700
result is 900
doIt: 1502.43701171875 ms
*/

修改业务,每一个步骤都需要之前每个步骤的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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(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);
}

async function doIt() {
try{
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");
}
catch (err) {
console.error(err);
}
}

doIt();

/*
step1 with 300
step2 with 300 and 500 (300 + 200 == 500)
step3 with 300, 500 and 1000 (300 + 500 + 200 == 1000)
result is 2000 (300 + 500 + 1000 + 200 == 2000)
doIt: 3764.155029296875 ms
*/