mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 18:32:22 +00:00
docs(set): edit set
This commit is contained in:
parent
ad472cdf6a
commit
aab07bdbc8
@ -742,9 +742,9 @@ function* somethingAsync(x) {
|
|||||||
|
|
||||||
### 含义
|
### 含义
|
||||||
|
|
||||||
ES7提供了`async`函数,使得异步操作变得更加方便。`async`函数是什么?一句话,`async`函数就是Generator函数的语法糖。
|
ES2017 标准提供了`async`函数,使得异步操作变得更加方便。
|
||||||
|
|
||||||
前文有一个Generator函数,依次读取两个文件。
|
`async`函数是什么?一句话,`async`函数就是 Generator 函数的语法糖。前文有一个 Generator 函数,依次读取两个文件。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
@ -777,25 +777,25 @@ 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
|
```javascript
|
||||||
var result = asyncReadFile();
|
var result = asyncReadFile();
|
||||||
```
|
```
|
||||||
|
|
||||||
上面的代码调用了`asyncReadFile`函数,然后它就会自动执行,输出最后结果。这完全不像Generator函数,需要调用`next`方法,或者用`co`模块,才能得到真正执行,得到最后结果。
|
上面的代码调用了`asyncReadFile`函数,然后它就会自动执行,输出最后结果。这完全不像 Generator 函数,需要调用`next`方法,或者用`co`模块,才能得到真正执行,得到最后结果。
|
||||||
|
|
||||||
(2)更好的语义。`async`和`await`,比起星号和`yield`,语义更清楚了。`async`表示函数里有异步操作,`await`表示紧跟在后面的表达式需要等待结果。
|
(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`命令的语法糖。
|
进一步说,`async`函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而`await`命令就是内部`then`命令的语法糖。
|
||||||
|
|
||||||
### 语法
|
### 语法
|
||||||
|
|
||||||
@ -816,7 +816,7 @@ f().then(v => console.log(v))
|
|||||||
|
|
||||||
上面代码中,函数`f`内部`return`命令返回的值,会被`then`方法回调函数接收到。
|
上面代码中,函数`f`内部`return`命令返回的值,会被`then`方法回调函数接收到。
|
||||||
|
|
||||||
`async`函数内部抛出错误,会导致返回的Promise对象变为`reject`状态。抛出的错误对象会被`catch`方法回调函数接收到。
|
`async`函数内部抛出错误,会导致返回的 Promise 对象变为`reject`状态。抛出的错误对象会被`catch`方法回调函数接收到。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
async function f() {
|
async function f() {
|
||||||
@ -830,7 +830,7 @@ f().then(
|
|||||||
// Error: 出错了
|
// Error: 出错了
|
||||||
```
|
```
|
||||||
|
|
||||||
(2)`async`函数返回的Promise对象,必须等到内部所有`await`命令的Promise对象执行完,才会发生状态改变。也就是说,只有`async`函数内部的异步操作执行完,才会执行`then`方法指定的回调函数。
|
(2)`async`函数返回的 Promise 对象,必须等到内部所有`await`命令的Promise对象执行完,才会发生状态改变,除非遇到`return`语句或者抛出错误。也就是说,只有`async`函数内部的异步操作执行完,才会执行`then`方法指定的回调函数。
|
||||||
|
|
||||||
下面是一个例子。
|
下面是一个例子。
|
||||||
|
|
||||||
@ -844,7 +844,9 @@ getTitle('https://tc39.github.io/ecma262/').then(console.log)
|
|||||||
// "ECMAScript 2017 Language Specification"
|
// "ECMAScript 2017 Language Specification"
|
||||||
```
|
```
|
||||||
|
|
||||||
(3)正常情况下,`await`命令后面是一个Promise对象。如果不是,会被转成一个立即`resolve`的Promise对象。
|
上面代码中,函数`getTitle`内部有三个操作:抓取网页、取出文本、匹配页面标题。只有这三个操作全部完成,才会执行`then`方法里面的`console.log`。
|
||||||
|
|
||||||
|
(3)正常情况下,`await`命令后面是一个 Promise 对象。如果不是,会被转成一个立即`resolve`的 Promise 对象。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
async function f() {
|
async function f() {
|
||||||
@ -1008,8 +1010,6 @@ function spawn(genF) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`async`函数是非常新的语法功能,新到都不属于 ES6,而是属于 ES7。目前,它仍处于提案阶段,但是转码器`Babel`和`regenerator`都已经支持,转码后就能使用。
|
|
||||||
|
|
||||||
### async 函数的用法
|
### async 函数的用法
|
||||||
|
|
||||||
`async`函数返回一个Promise对象,可以使用`then`方法添加回调函数。当函数执行的时候,一旦遇到`await`就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
|
`async`函数返回一个Promise对象,可以使用`then`方法添加回调函数。当函数执行的时候,一旦遇到`await`就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
|
||||||
@ -1047,7 +1047,7 @@ async function asyncPrint(value, ms) {
|
|||||||
asyncPrint('hello world', 50);
|
asyncPrint('hello world', 50);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码指定50毫秒以后,输出"hello world"。
|
上面代码指定50毫秒以后,输出`hello world`。
|
||||||
|
|
||||||
Async函数有多种使用形式。
|
Async函数有多种使用形式。
|
||||||
|
|
||||||
@ -1323,7 +1323,7 @@ async function logInOrder(urls) {
|
|||||||
|
|
||||||
## 异步遍历器
|
## 异步遍历器
|
||||||
|
|
||||||
《遍历器》一章说过,Iterator接口是一种数据遍历的协议,只要调用遍历器对象的`next`方法,就会得到一个表示当前成员信息的对象`{value, done}`。其中,`value`表示当前的数据的值,`done`是一个布尔值,表示遍历是否结束。
|
《遍历器》一章说过,Iterator 接口是一种数据遍历的协议,只要调用遍历器对象的`next`方法,就会得到一个表示当前成员信息的对象`{value, done}`。其中,`value`表示当前的数据的值,`done`是一个布尔值,表示遍历是否结束。
|
||||||
|
|
||||||
这隐含着规定,`next`方法是同步的,只要调用就必须立刻返回值。也就是说,一旦执行`next`方法,就必须同步地得到`value`和`done`这两方面的信息。这对于同步操作,当然没有问题,但对于异步操作,就不太合适了。目前的解决方法是,Generator函数里面的异步操作,返回一个Thunk函数或者Promise对象,即`value`属性是一个Thunk函数或者Promise对象,等待以后返回真正的值,而`done`属性则还是同步产生的。
|
这隐含着规定,`next`方法是同步的,只要调用就必须立刻返回值。也就是说,一旦执行`next`方法,就必须同步地得到`value`和`done`这两方面的信息。这对于同步操作,当然没有问题,但对于异步操作,就不太合适了。目前的解决方法是,Generator函数里面的异步操作,返回一个Thunk函数或者Promise对象,即`value`属性是一个Thunk函数或者Promise对象,等待以后返回真正的值,而`done`属性则还是同步产生的。
|
||||||
|
|
||||||
@ -1587,3 +1587,4 @@ async function* gen2() {
|
|||||||
// a
|
// a
|
||||||
// b
|
// b
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ Set结构的实例有四个遍历方法,可以用于遍历成员。
|
|||||||
|
|
||||||
**(1)`keys()`,`values()`,`entries()`**
|
**(1)`keys()`,`values()`,`entries()`**
|
||||||
|
|
||||||
`key`方法、`value`方法、`entries`方法返回的都是遍历器对象(详见《Iterator对象》一章)。由于Set结构没有键名,只有键值(或者说键名和键值是同一个值),所以`key`方法和`value`方法的行为完全一致。
|
`keys`方法、`values`方法、`entries`方法返回的都是遍历器对象(详见《Iterator 对象》一章)。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以`keys`方法和`values`方法的行为完全一致。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
let set = new Set(['red', 'green', 'blue']);
|
let set = new Set(['red', 'green', 'blue']);
|
||||||
|
@ -303,7 +303,7 @@ let obj = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Reflect.ownKeys(obj)
|
Reflect.ownKeys(obj)
|
||||||
// [Symbol(my_key), 'enum', 'nonEnum']
|
// ["enum", "nonEnum", Symbol(my_key)]
|
||||||
```
|
```
|
||||||
|
|
||||||
由于以 Symbol 值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。
|
由于以 Symbol 值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。
|
||||||
|
Loading…
x
Reference in New Issue
Block a user