edit async

This commit is contained in:
ruanyf
2016-01-22 23:46:11 +08:00
parent f5d01f117d
commit 29e8701258
2 changed files with 36 additions and 13 deletions
+35 -13
View File
@@ -697,7 +697,7 @@ function* somethingAsync(x) {
### 含义
ES7提供了`async`函数,使得异步操作变得更加方便。async 函数是什么?一句话,async函数就是Generator函数的语法糖。
ES7提供了`async`函数,使得异步操作变得更加方便。`async`函数是什么?一句话,`async`函数就是Generator函数的语法糖。
前文有一个Generator函数,依次读取两个文件。
@@ -732,23 +732,23 @@ var asyncReadFile = async function (){
};
```
一比较就会发现,async函数就是将Generator函数的星号(*)替换成async,将yield替换成await,仅此而已。
一比较就会发现,`async`函数就是将Generator函数的星号(`*`)替换成`async`,将`yield`替换成`await`,仅此而已。
async 函数对 Generator 函数的改进,体现在以下三点。
`async`函数对 Generator 函数的改进,体现在以下三点。
(1)内置执行器。Generator函数的执行必须靠执行器,所以才有了co模块,而async 函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
(1)内置执行器。Generator函数的执行必须靠执行器,所以才有了`co`模块,而`async`函数自带执行器。也就是说,`async`函数的执行,与普通函数一模一样,只要一行。
```javascript
var result = asyncReadFile();
```
上面的代码调用了`asyncReadFile`函数,然后它就会自动执行,输出最后结果。这完全不像Generator函数,需要调用`next`方法,或者用co模块,才能得到真正执行,得到最后结果。
上面的代码调用了`asyncReadFile`函数,然后它就会自动执行,输出最后结果。这完全不像Generator函数,需要调用`next`方法,或者用`co`模块,才能得到真正执行,得到最后结果。
2)更好的语义。`async``await`,比起星号和`yield`,语义更清楚了。`async`表示函数里有异步操作,`await`表示紧跟在后面的表达式需要等待结果。
3)更广的适用性。 co模块约定,`yield`命令后面只能是Thunk函数或Promise对象,而`async`函数的`await`命令后面,可以是Promise对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
3)更广的适用性。 `co`模块约定,`yield`命令后面只能是Thunk函数或Promise对象,而`async`函数的`await`命令后面,可以是Promise对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
4)返回值是Promise。async函数的返回值是Promise对象,这比Generator函数的返回值是Iterator对象方便多了。你可以用`then`方法指定下一步的操作。
4)返回值是Promise。`async`函数的返回值是Promise对象,这比Generator函数的返回值是Iterator对象方便多了。你可以用`then`方法指定下一步的操作。
进一步说,async函数完全可以看作多个异步操作,包装成的一个Promise对象,而`await`命令就是内部`then`命令的语法糖。
@@ -841,7 +841,7 @@ asyncPrint('hello world', 50);
### 注意点
await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。
第一点,`await`命令后面的Promise对象,运行结果可能是rejected,所以最好把`await`命令放在`try...catch`代码块中。
```javascript
async function myFunction() {
@@ -861,7 +861,29 @@ async function myFunction() {
}
```
await命令只能用在async函数之中,如果用在普通函数,就会报错
第二点,多个`await`命令后面的异步操作,如果不存在继发关系,最好让它们同时触发
```javascript
let foo = await getFoo();
let bar = await getBar();
```
上面代码中,`getFoo``getBar`是两个独立的异步操作(即互不依赖),被写成继发关系。这样比较耗时,因为只有`getFoo`完成以后,才会执行`getBar`,完全可以让它们同时触发。
```javascript
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
```
上面两种写法,`getFoo``getBar`都是同时触发,这样就会缩短程序的执行时间。
第三点,`await`命令只能用在`async`函数之中,如果用在普通函数,就会报错。
```javascript
async function dbFuc(db) {
@@ -874,7 +896,7 @@ async function dbFuc(db) {
}
```
上面代码会报错,因为await用在普通函数之中了。但是,如果将forEach方法的参数改成async函数,也有问题。
上面代码会报错,因为await用在普通函数之中了。但是,如果将`forEach`方法的参数改成`async`函数,也有问题。
```javascript
async function dbFuc(db) {
@@ -887,7 +909,7 @@ async function dbFuc(db) {
}
```
上面代码可能不会正常工作,原因是这时三个`db.post`操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用for循环。
上面代码可能不会正常工作,原因是这时三个`db.post`操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用`for`循环。
```javascript
async function dbFuc(db) {
@@ -899,7 +921,7 @@ async function dbFuc(db) {
}
```
如果确实希望多个请求并发执行,可以使用 Promise.all 方法。
如果确实希望多个请求并发执行,可以使用`Promise.all`方法。
```javascript
async function dbFuc(db) {
@@ -924,7 +946,7 @@ async function dbFuc(db) {
}
```
ES6将await增加为保留字。使用这个词作为标识符,在ES5是合法的,在ES6将抛出SyntaxError。
ES6将`await`增加为保留字。使用这个词作为标识符,在ES5是合法的,在ES6将抛出SyntaxError。
### 与Promise、Generator的比较
+1
View File
@@ -161,6 +161,7 @@
- Jafar Husain, [Asynchronous Generators for ES7](https://github.com/jhusain/asyncgenerator): Async函数的深入讨论
- 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的关系
## Class