From e0f36e61fc6a83caa002abdc75ac5e946cbf9a62 Mon Sep 17 00:00:00 2001 From: ruanyf Date: Mon, 24 Oct 2016 19:57:17 +0800 Subject: [PATCH] docs(async): edit async --- docs/async.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++- docs/reference.md | 1 + 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/docs/async.md b/docs/async.md index 257d4bb..af377df 100644 --- a/docs/async.md +++ b/docs/async.md @@ -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`是一个布尔值,表示遍历是否结束。 diff --git a/docs/reference.md b/docs/reference.md index b0b0e37..90db618 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -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