为什么要有异步迭代器
同步迭代器里数据都是当时就能获取的(没有延迟),而异步迭代器里的数据往往获取是需要时间的(有延迟)。
如果同步迭代器数据获取需要时间(比如实际场景中请求接口),那么再用 for-of 遍历的话,就有问题——控制不了数据的处理顺序。
1 2 3 4 5 6 7 8 9 10 11
   | let obj = {   *[Symbol.iterator]() {     yield 1;     yield 2;     yield 3;   } }
  for (let item of obj) { 	console.log(item)  }
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   |  const obj = {   *[Symbol.iterator]() {     yield new Promise(resolve => setTimeout(() => resolve(1), 5000));     yield new Promise(resolve => setTimeout(() => resolve(2), 2000));     yield new Promise(resolve => setTimeout(() => resolve(3), 500));   } }
  console.log(Date.now()) for (let item of obj) {     item.then(data => console.log(Date.now(), data)) }
 
 
 
 
 
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | let obj = {   async *[Symbol.asyncIterator]() {     yield new Promise(resolve => setTimeout(() => resolve(1), 2000));     yield new Promise(resolve => setTimeout(() => resolve(2), 1000));     yield new Promise(resolve => setTimeout(() => resolve(3), 500));   } }
  async function test(){   console.log(Date.now())   for await (let item of obj) {   	console.log(Date.now(), item)   } }
  test()
 
 
 
 
 
  | 
 
注意,异步迭代器要声明在 [Symbol.asyncIterator] 属性里,使用 for-await-of 循环处理的。 最终效果是,对任务挨个处理,上一个任务等待处理完毕后,再进入下一个任务。
异步迭代器
与同步可迭代对象部署了 [Symbol.iterator] 属性不同的是,异步可迭代对象的标志是部署了 [Symbol.asyncIterator] 这个属性。
异步迭代器用来处理不能即时拿到数据的情况,还能保证最终的处理顺序等于遍历顺序,不过需要依次排队等待。
与同步迭代器 iterator 不同的是,在 asyncIterator 上调用 next 方法得到是一个 Promise 对象,其内部值是 { value: xx, done: xx } 的形式,类似于 Promise.resolve({ value: xx, done: xx }) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  const obj = {   async *[Symbol.asyncIterator]() {     yield 1;     yield 2;     yield 3;   } }
  const asyncIterator = obj[Symbol.asyncIterator]()
  asyncIterator.next().then(data => console.log(data))  asyncIterator.next().then(data => console.log(data))  asyncIterator.next().then(data => console.log(data))  asyncIterator.next().then(data => console.log(data)) 
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | const justjavac = {   [Symbol.asyncIterator]: () => {     const items = [`j`, `u`, `s`, `t`, `j`, `a`, `v`, `a`, `c`];     return {       next: () => Promise.resolve({         done: items.length === 0,         value: items.shift()       })     }   } } ;(async function(){   for await (const item of justjavac) {     console.log(item)   } })();
 
 
 
 
 
 
 
 
 
 
  | 
 
同步迭代器vs异步迭代器
Iterator
1 2 3 4 5 6 7 8 9 10 11 12
   |  interface Iterator {     next(value) : IteratorResult;     [optional] throw(value) : IteratorResult;     [optional] return(value) : IteratorResult; }
 
  interface IteratorResult {     value : any;     done : bool; }
 
  | 
 
Async Iterators
1 2 3 4 5 6 7 8 9 10 11 12
   |  interface AsyncIterator {     next(value) : Promise<IteratorResult>;     [optional] throw(value) : Promise<IteratorResult>;     [optional] return(value) : Promise<IteratorResult>; }
 
  interface IteratorResult {     value : any;     done : bool; }
 
  | 
 
异步迭代语句
for await...of 语句创建一个循环,该循环遍历 异步可迭代对象 以及 同步可迭代对象。该语句只能在可以使用 await 的上下文中使用 ,包括异步函数体内以及模块中。 也就是说 for-await-of 语句除了能用在异步可迭代对象上,还能用在同步可迭代对象上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | async function* asyncGenerator() {   yield new Promise(resolve => setTimeout(() => resolve('First'), 3000));   yield new Promise(resolve => setTimeout(() => resolve('Second'), 2000));   yield new Promise(resolve => setTimeout(() => resolve('Third'), 1000)); }
  async function test() {   for await (let result of asyncGenerator()) {     console.log(Date.now(), Date.now() - pre, result);   } } const pre = Date.now(); test();
 
 
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12
   | const obj = {   *[Symbol.iterator]() {     yield 1     yield 2     yield 3   } }; (async () => {   for await(const item of obj) {     console.log(item)    } })()
  | 
 
注意是顺序问题:
- 如果一个对象上同时部署了 
[Symbol.asyncIterator] 和 [Symbol.iterator] ,那就会优先使用 [Symbol.asyncIterator] 生成的异步迭代器。这很好理解,因为 for-await-of 本来就是为异步迭代器而生的。 
- 相反如果同时部署了两个迭代器,但使用的是
for-of那么优先使用同步迭代器。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
   | const obj = {   *[Symbol.iterator]() {     yield 1     yield 2     yield 3   },   async *[Symbol.asyncIterator]() {     yield 4     yield 5     yield 6   } }
 
  ;(async () => {   for await(const item of obj) {     console.log(item)    } })()
 
  for (const item of obj) { 	console.log(item)  }
 
 
 
 
 
 
 
  | 
 
异步生成器函数
异步生成器函数与生成器函数类似,但有以下区别:
- 当被调用时,异步生成器函数返回一个对象,”
async generator“,含有 3 个方法( next , throw ,和return ),每个方法都返回一个 Promise,Promise 返回 { value, done } 。而普通生成器函数并不返回 Promise,而是直接返回 { value, done }。 这会自动使返回的异步生成器对象具有异步迭代的功能。 
- 允许使用 
await表达式和 for-await-of 语句。 
- 修改了 
yield* 的行为以支持异步迭代。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   |  async function* asyncGenerator() {   let count = 3;   while (count >= 1) {          let delay = count * 1000;     let result = await new Promise(resolve => setTimeout(() => resolve(`Result ${count}`), delay));     yield result;     count--;   } }
 
  async function processData() {      for await (let result of asyncGenerator()) {     console.log(Date.now(), Date.now() - pre, result);   } }
  const pre = Date.now();
  processData();
 
 
 
 
  |