前方提醒: 篇幅较长,点个赞或者收藏一下,能够在下一次阅读时方便查找es6
ES9新增了异步迭代器(Async iterator),异步执行语句(for...await...of)和异步生成器(Async generator),本文带领你们了解这三个新特性,以及如何建立异步迭代器。数组
若是你还不了解ES6的
迭代器
,也就是iterator
,先来看看这一部分。markdown
iterator
是一个特殊的对象,它包含一个next
方法,next
方法返回一个对象,这个对象包含两个属性,一个是value
,表示成员的值,一个是done
,done
的值是一个布尔类型
,表示迭代器
是否结束。数据结构
iterator.next() // 返回 {value: '', done: false} 复制代码
迭代器
内部会保存一个指针,指向迭代器的成员位置,每调用一次next
方法,指针就会移动到下一个成员,直到指针指向迭代器最后一个成员后面的位置,这时,done
的值为true
,value
的值通常为undefined
,须要根据iterator
的实际实现来决定。异步
实现一个函数,用来建立
iterator
。async
几个关键点函数
iterator
是一个对象,而且含有一个next
方法next
方法返回一个对象,包含一个value
属性和done
属性,value
表示返回的值,done
是一个布尔类型,表示迭代器是否结束iterator
内部包含一个内部指针,指向迭代器的成员的位置,每调用一次next
方法,指针就会移动到下一个成员,直到指针指向迭代器最后一个成员后面的位置,这时done
的值为true
// 能够经过传入数组或者对象建立iterator const createIterator = items => { const keys = Object.keys(items) const len = keys.length let pointer = 0 return { next() { const done = pointer >= len const value = !done ? items[keys[pointer++]] : undefined return { value, done } } } } 复制代码
const iterator1 = createIterator([1, 2, 3]) iterator.next() // { value: 1, done: false } iterator.next() // { value: 2, done: false } iterator.next() // { value: 3, done: false } iterator.next() // { value: undefined, done: true } 复制代码
const iterator2 = createIterator({a: 'a', b: 'b', c: 'c'}) iterator.next() // { value: 'a', done: false } iterator.next() // { value: 'b', done: false } iterator.next() // { value: 'c', done: false } iterator.next() // { value: undefined, done: true } 复制代码
部署了iterator
接口的数据结构,也就是具备Symbol.iterator
方法的数据结构,就能够被for...of
遍历。Symbol.iterator
方法相似于上面实现的createIterator
函数oop
iterator
接口const arr = [1, 2, 3] typeof arr[Symbol.iterator] // 'function' for (const val of arr) { console.log(val) } // 1 // 2 // 3 复制代码
iterator
接口,可是咱们能够本身部署const obj = {a: 'a', b: 'b', c: 'c'} typeof obj[Symbol.iterator] // 'undefined' for (const val of obj) { console.log(val) } // TypeError: obj is not iterable 复制代码
给对象部署iterator
接口this
const obj = {a: 'a', b: 'b', c: 'c'} obj[Symbol.iterator] = function() { const self = this const keys = Object.keys(self) const len = keys.length let pointer = 0 return { next() { const done = pointer >= len const value = !done ? self[keys[pointer++]] : undefined return { value, done } } } } for (const val of obj) { console.log(val) } // a // b // c 复制代码
Generator
是一个特殊的函数,函数体内部使用yield
表达式,定义不一样的内部状态,当执行Generator
函数时,不会直接执行函数体,而是会返回一个遍历器对象(iterator)。spa
Generator
函数内部可使用yield
表达式,定义内部状态function
关键字与函数名之间有一个*
function* generator() { console.log('start'); yield 1 yield 2 yield 3 console.log('end') } const iterator = generator() // 这时函数体并无被执行,而是建立了一个iterator // 当调用iterator的next方法时,函数体开始执行, iterator.next() // 'start' {value: 1, done: false} iterator.next() // {value: 2, done: false} iterator.next() // {value: 3, done: false} iterator.next() // 'end' {value: undefined, done: true} 复制代码
next
方法,函数体会从函数头部或上次停下来的地方开始执行,直到遇到下一个yield
表达式或者return
语句时中止yield
表达式后面的值会做为next
方法返回的对象的value
属性值return
会做为iterator
结束的标记,而且retur
n的值会做为next
方法返回的对象的value属性值改写一下上面的例子
function* generator() { yield 1 yield 2 return 3 } const iterator = generator() // 当调用iterator的next方法时,函数体开始执行, iterator.next() // {value: 1, done: false} iterator.next() // {value: 2, done: false} iterator.next() // {value: 3, done: true} 复制代码
Generator
函数生成的iterator
能够被for...of
遍历
function* generator() { yield 1 yield 2 yield 3 } const iterator = generator() typeof iterator[Symbol.iterator] // 'function' for (const val of iterator) { console.log(val) } // 1 // 2 // 3 复制代码
在这里咱们只须要知道Generator
函数会生成一个iterator
就够了,但实际上Generator
函数远不止这些,这里咱们不作详细介绍了,感兴趣的同窗能够看看阮一峰Generator教程
ES9新增了异步迭代器
异步迭代器
和同步迭代器
相同,都是一个函数,而且含有一个next
方法,区别在于同步迭代器
的next
方法返回一个含有value
和done
属性的对象,而异步迭代器
的next
方法返回一个Promise
对象,而且Promise
对象的值为含有value
和done
属性的对象。
// 这是一个异步迭代器 asyncIterator.next().then(res => { console.log(res.value, res.done) }) 复制代码
咱们来实现一个建立异步迭代器
的方法
const createAsyncIterator = items => { const keys = Object.keys(items) const len = keys.length let pointer = 0 return { next() { const done = pointer >= len const value = !done ? items[keys[pointer++]] : undefined return Promise.resolve({ value, done }) } } } 复制代码
和同步迭代器
相同,每调用一次next
方法,异步迭代器
内部的指针就移动到下一个成员
const aynscIterator = createAsyncIterator([1, 2, 3]) aynscIterator.next().then(({value, done}) => { console.log(value, done) // 1 false }) aynscIterator.next().then(({value, done}) => { console.log(value, done) // 2 false }) aynscIterator.next().then(({value, done}) => { console.log(value, done) // 3 false }) aynscIterator.next().then(({value, done}) => { console.log(value, done) // undefined true }) 复制代码
for...of
方法可以遍历具备Symbol.iterator
接口的同步迭代器
数据,可是不能遍历异步迭代器
。 ES9新增的for...await...of
能够用来遍历具备Symbol.asyncIterator
方法的数据结构,也就是异步迭代器
,且会等待前一个成员的状态改变后才会遍历到下一个成员,至关于async
函数内部的await
。
定义一个具备Symbol.asyncIterator
方法的对象
const asyncItems = { a: 1, b: 2, c: 3, [Symbol.asyncIterator]() { const items = this const keys = Object.keys(items) const len = keys.length let pointer = 0 return { next() { const done = pointer >= len const value = !done ? items[keys[pointer++]] : undefined; return new Promise((resolve) => { setTimeout(() => { resolve({value, done}) }, 1000) }) } } } } 复制代码
使用for...await...of
遍历该对象
// await只能用在async函数中 async function run() { for await (const value of asyncItems) { console.log(value); } } run(); // 1s后打印出 1 // 再过1s后打印出 2 // 再过1s后打印出 3 复制代码
上面的例子实现了每隔1s打印出对象的属性值的异步遍历器接口
,能够看到, 当使用for...await..of
,遍历时,会等待前一个Promise
对象的状态改变后,再遍历到下一个成员。
咱们能够采起一种更方便的方式建立异步迭代器
,就是利用异步生成器
。
异步生成器
和普通的生成器很像,可是其是async
函数,内部可使用await
表达式,而且它返回一个具备Symbol.asyncIterator
方法的对象。
定义一个异步生成器
async function* asyncGenerator() { yield await Promise.resolve(1); yield await Promise.resolve(2); yield await Promise.resolve(3); } 复制代码
使用for...await...of
遍历该对象
const asyncIterator = asyncGenerator() typeof asyncIterator[Symbol.asyncIterator] // 'function' async function run() { for await (const value of asyncIterator) { console.log(value); } } run(); // 1 // 2 // 3 复制代码
异步迭代器
与同步迭代器
相同的是,异步迭代器
也是一个具备next
方法的对象异步迭代器
对象的next
方法返回一个Promise对象
,Promise对象
的值为一个对象,包含一个value属性和一个done属性for...await...of
能够遍历具备Symbol.asyncIterator
方法的数据结构,而且会等待上一个成员状态改变后再继续执行异步生成器
(Async Generator)能够用来建立异步迭代器
,它是一个async
类型的generator
函数,内部可使用await
表达式等待异步方法的执行完成,并使用for...await...of
遍历