mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 10:22:23 +00:00
docs(async): edit async
This commit is contained in:
parent
5258e43dd0
commit
e0f36e61fc
@ -1060,6 +1060,22 @@ const foo = async function () {};
|
||||
|
||||
// 对象的方法
|
||||
let obj = { async foo() {} };
|
||||
obj.foo().then(...)
|
||||
|
||||
// Class 的方法
|
||||
class Storage {
|
||||
constructor() {
|
||||
this.cachePromise = caches.open('avatars');
|
||||
}
|
||||
|
||||
async getAvatar(name) {
|
||||
const cache = await this.cachePromise;
|
||||
return cache.match(`/avatars/${name}.jpg`);
|
||||
}
|
||||
}
|
||||
|
||||
const storage = new Storage();
|
||||
storage.getAvatar('jake').then(…);
|
||||
|
||||
// 箭头函数
|
||||
const foo = async () => {};
|
||||
@ -1067,7 +1083,7 @@ const foo = async () => {};
|
||||
|
||||
### 注意点
|
||||
|
||||
第一点,`await`命令后面的Promise对象,运行结果可能是rejected,所以最好把`await`命令放在`try...catch`代码块中。
|
||||
第一点,`await`命令后面的`Promise`对象,运行结果可能是`rejected`,所以最好把`await`命令放在`try...catch`代码块中。
|
||||
|
||||
```javascript
|
||||
async function myFunction() {
|
||||
@ -1252,6 +1268,59 @@ async function chainAnimationsAsync(elem, animations) {
|
||||
|
||||
可以看到Async函数的实现最简洁,最符合语义,几乎没有语义不相关的代码。它将Generator写法中的自动执行器,改在语言层面提供,不暴露给用户,因此代码量最少。如果使用Generator写法,自动执行器需要用户自己提供。
|
||||
|
||||
### 实例:按顺序完成异步操作
|
||||
|
||||
实际开发中,经常遇到一组异步操作,需要按照顺序完成。比如,依次远程读取一组URL,然后按照读取的顺序输出结果。
|
||||
|
||||
Promise 的写法如下。
|
||||
|
||||
```javascript
|
||||
function logInOrder(urls) {
|
||||
// 远程读取所有URL
|
||||
const textPromises = urls.map(url => {
|
||||
return fetch(url).then(response => response.text());
|
||||
});
|
||||
|
||||
// 按次序输出
|
||||
textPromises.reduce((chain, textPromise) => {
|
||||
return chain.then(() => textPromise)
|
||||
.then(text => console.log(text));
|
||||
}, Promise.resolve());
|
||||
}
|
||||
```
|
||||
|
||||
上面代码使用`fetch`方法,同时远程读取一组URL。每个`fetch`操作都返回一个`Promise`对象,放入`textPromises`数组。然后,`reduce`方法依次处理每个`Promise`对象,然后使用`then`,将所有`Promise`对象连起来,因此就可以依次输出结果。
|
||||
|
||||
这种写法不太直观,可读性比较差。下面是`async`函数实现。
|
||||
|
||||
```javascript
|
||||
async function logInOrder(urls) {
|
||||
for (const url of urls) {
|
||||
const response = await fetch(url);
|
||||
console.log(await response.text());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上面代码确实大大简化,问题是所有远程操作都是继发。只有前一个URL返回结果,才会去读取下一个URL,这样做效率很差,非常浪费时间。我们需要的是并发发出远程请求。
|
||||
|
||||
```javascript
|
||||
async function logInOrder(urls) {
|
||||
// 并发读取远程URL
|
||||
const textPromises = urls.map(async url => {
|
||||
const response = await fetch(url);
|
||||
return response.text();
|
||||
});
|
||||
|
||||
// 按次序输出
|
||||
for (const textPromise of textPromises) {
|
||||
console.log(await textPromise);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上面代码中,虽然`map`方法的参数是`async`函数,但它是并发执行的,因为只有`async`函数内部是继发执行,外部不受影响。后面的`for..of`循环内部使用了`await`,因此实现了按顺序输出。
|
||||
|
||||
## 异步遍历器
|
||||
|
||||
《遍历器》一章说过,Iterator接口是一种数据遍历的协议,只要调用遍历器对象的`next`方法,就会得到一个表示当前成员信息的对象`{value, done}`。其中,`value`表示当前的数据的值,`done`是一个布尔值,表示遍历是否结束。
|
||||
|
@ -168,6 +168,7 @@
|
||||
- Nolan Lawson, [Taming the asynchronous beast with ES7](http://pouchdb.com/2015/03/05/taming-the-async-beast-with-es7.html): async函数通俗的实例讲解
|
||||
- Jafar Husain, [Async Generators](https://docs.google.com/file/d/0B4PVbLpUIdzoMDR5dWstRllXblU/view?sle=true): 对async与Generator混合使用的一些讨论
|
||||
- Daniel Brain, [Understand promises before you start using async/await](https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8): 讨论async/await与Promise的关系
|
||||
- Jake Archibald, [Async functions - making promises friendly](https://developers.google.com/web/fundamentals/getting-started/primers/async-functions)
|
||||
- Axel Rauschmayer, [ES proposal: asynchronous iteration](http://www.2ality.com/2016/10/asynchronous-iteration.html): 异步遍历器的详细介绍
|
||||
|
||||
## Class
|
||||
|
Loading…
x
Reference in New Issue
Block a user