ES 6 系列之三种异步 - Async/await

介绍

async 函数时什么,其实就是 Generator 的语法糖,只需要将 * 改写成 asyncyield 改写成 await
我们来看看 Generator 的写法,与 async 的写法。

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
const readFile = function (fileName, ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(fileName);
resolve(fileName); // 需要给 `Promise` 一个状态转化,就是异步执行是否成功
}, ms);
});
};

function* genator() {
yield readFile('fileName1', 1000);
yield readFile('fileName2', 2000);
yield readFile('fileName3', 3000);
console.log('打印完毕');
}
const gen = genator();
gen.next(); // fileName1
gen.next(); // fileName2
gen.next(); // fileName3

async function asyncTest() {
await readFile('fileName1', 1000);
await readFile('fileName2', 2000);
await readFile('fileName3', 3000);
console.log('执行完毕');
}
asyncTest();
// fileName1
// fileName2
// fileName3
// 执行完毕

从上面我们可以看出,我们需要手动调用 next 方法,来执行下一步。
async 有自己内置执行器。

我们来看看 asyncGenerator 的改进。

  • 内置执行器
    Generator 函数执行需要 next 执行器,外面手动调用,所以有 co 模块,而 async 函数自带执行器,与普通函数一样,只需要一行调用。
    下面代码中,调用了该函数之后,就会自动执行,输出最后结果。
1
asyncTest();
  • 语义更好
    async/await,比起 Generator 函数的 *yield,语义更清晰。 async 就表示异步,而 await 表示后面的表达式需要等待结果。

  • 适用性更强
    co 模块约定,yield 后面只能是 Thunk 函数或者 Promise 对象,而 await 后面可以是 Promise,也可以是原始类型值。

  • 返回值是 Promise
    async 函数返回值是 Promise 对象,可以用 then 方法来进行下一步操作。
    await 命令就是内部 then 命令的语法糖。

用法

返回 Promise 对象

  • async 函数返回一个 Promise 对象,可以使用 then 方法加入回调函数。
  • 执行函数时,遇到 await 就会先返回,等异步操作结束,再继续执行函数体后面的语句。
  • 必须等到内部所有 await 命令后面的 Promise 对象执行完毕,状态才会改变,除非遇到 return 或者报错。
  • async 函数内部的异步操作执行完毕,就可以执行 then 方法。
  • JS 没有休眠的语法,但是借助 await 命令就可以让程序停顿一定的时间。
1
2
3
4
5
6
7
8
9
10
async function useAsync() {
// readFile 使用的是本文顶部的方法
const result = await readFile('fileName', 1000);
return result;
}
useAsync().then((value) => {
console.log(value);
});
// fileName
// fileName
  • 如果返回 reject 状态,则会中断执行,并通过 catch 捕获
1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function useAsync() {
// readFile 使用的是本文顶部的方法
const result = await Promise.reject('测试错误');
console.log('打印?');
return result;
}
useAsync()
.then((value) => {
console.log(value);
})
.catch((error) => {
console.log(error);
});
// 测试错误

await 命令

await 命令后面是一个 Promise 对象,返回结果。如果不是 Promise,就直接返回对应值。

  • await 命令只能出现在 async 命令函数内部,不然会报错。
1
2
3
4
5
6
7
8
9
10
11
const add = (a, b) => {
return a + b;
};
async function useAsync() {
const result = await add(1, 2);
return result;
}
useAsync().then((value) => {
console.log(value);
});
// 3

await 后面跟着 add 方法,算出一个数值 3,然后将值 return 出来。


简单的 await 使用方法,就是如此。

-------------------- 本文结束 感谢阅读 --------------------