diff --git a/docs/async-iterator.md b/docs/async-iterator.md index 15570be..661b23d 100644 --- a/docs/async-iterator.md +++ b/docs/async-iterator.md @@ -1,8 +1,75 @@ # 异步遍历器 +## 同步遍历器的问题 + 《遍历器》一章说过,Iterator 接口是一种数据遍历的协议,只要调用遍历器对象的`next`方法,就会得到一个对象,表示当前遍历指针所在的那个位置的信息。`next`方法返回的对象的结构是`{value, done}`,其中`value`表示当前的数据的值,`done`是一个布尔值,表示遍历是否结束。 -这里隐含着一个规定,`next`方法必须是同步的,只要调用就必须立刻返回值。也就是说,一旦执行`next`方法,就必须同步地得到`value`和`done`这两个属性。如果遍历指针正好指向同步操作,当然没有问题,但对于异步操作,就不太合适了。目前的解决方法是,Generator 函数里面的异步操作,返回一个 Thunk 函数或者 Promise 对象,即`value`属性是一个 Thunk 函数或者 Promise 对象,等待以后返回真正的值,而`done`属性则还是同步产生的。 +```javascript +function idMaker() { + let index = 0; + + return { + next: function() { + return { value: index++, done: false }; + } + }; +} + +const it = idMaker(); + +it.next().value // 0 +it.next().value // 1 +it.next().value // 2 +// ... +``` + +上面代码中,变量`it`是一个遍历器(iterator)。每次调用`it.next()`方法,就返回一个对象,表示当前遍历位置的信息。 + +这里隐含着一个规定,`it.next()`方法必须是同步的,只要调用就必须立刻返回值。也就是说,一旦执行`it.next()`方法,就必须同步地得到`value`和`done`这两个属性。如果遍历指针正好指向同步操作,当然没有问题,但对于异步操作,就不太合适了。 + +```javascript +function idMaker() { + let index = 0; + + return { + next: function() { + return new Promise(function (resolve, reject) { + setTimeout(() => { + resolve({ value: index++, done: false }); + }, 1000); + }); + } + }; +} +``` + +上面代码中,`next()`方法返回的是一个 Promise 对象,这样就不行,不符合 Iterator 协议。也就是说,Iterator 协议里面`next()`方法只能包含同步操作。 + +目前的解决方法是,将异步操作包装成 Thunk 函数或者 Promise 对象,即`next()`方法返回值的`value`属性是一个 Thunk 函数或者 Promise 对象,等待以后返回真正的值,而`done`属性则还是同步产生的。 + +```javascript +function idMaker() { + let index = 0; + + return { + next: function() { + return { + value: new Promise(resolve => setTimeout(() => resolve(index++), 1000)), + done: false + }; + } + }; +} + +const it = idMaker(); + +it.next().value.then(o => console.log(o)) // 1 +it.next().value.then(o => console.log(o)) // 2 +it.next().value.then(o => console.log(o)) // 3 +// ... +``` + +上面代码中,`value`属性的返回值是一个 Promise 对象,用来放置异步操作。但是这样写很麻烦,不太符合直觉,语义也比较绕。 ES2018 [引入](https://github.com/tc39/proposal-async-iteration)了“异步遍历器”(Async Iterator),为异步操作提供原生的遍历器接口,即`value`和`done`这两个属性都是异步产生。 diff --git a/sidebar.md b/sidebar.md index 0e49041..8d3579f 100644 --- a/sidebar.md +++ b/sidebar.md @@ -26,13 +26,13 @@ 1. [Generator 函数的语法](#docs/generator) 1. [Generator 函数的异步应用](#docs/generator-async) 1. [async 函数](#docs/async) -1. [异步遍历器](#docs/async-iterator) 1. [Class 的基本语法](#docs/class) 1. [Class 的继承](#docs/class-extends) 1. [Module 的语法](#docs/module) 1. [Module 的加载实现](#docs/module-loader) 1. [编程风格](#docs/style) 1. [读懂规格](#docs/spec) +1. [异步遍历器](#docs/async-iterator) 1. [ArrayBuffer](#docs/arraybuffer) 1. [最新提案](#docs/proposals) 1. [Decorator](#docs/decorator)