SOURCE

/**
 * Iterator 接口是一种数据遍历的协议
 * 只要调用遍历器对象的next方法,就会得到一个对象
 * 表示当前遍历指针所在的那个位置的信息。
 * next方法返回的对象的结构是{value, done},其中value表示当前的数据的值
 * done是一个布尔值,表示遍历是否结束
 */
let idMaker = function () {
    let index = 0;

    return {
        next() {
            return { value: index++, done: false }
        }
    }
}

const it = idMaker()

console.log(it.next().value) // 0
console.log(it.next().value) // 1
console.log(it.next().value) // 2

/**
 * 上面代码中 it 就是一个遍历器(iterator)。每次调用 it.next() 方法就会返回
 * 一个对象,表示当前遍历位置的信息
 * 
 * 但是这里其实是有些问题的,首先 it.next() 方法必须是同步的,只要调用就必须立刻返回值
 * 也就是说,一旦执行 it.next() 方法,就必须同步得到value 和 done 这两个属性
 * 乍一看好像没什么问题,但是如果是异步操作就有问题了
 * 例如:
 * */

let idMaker2 = function () {
    let index = 0

    return {
        next: function () {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve({ value: index++, done: false })
                }, 1000)
            })
        }
    }
}

/**
 * 这样的话,next()返回的就是个promise对象,这样的话是不符合Iterator协议
 * 
 * 目前解决办法是,将异步操作封装成Thunk函数或者Promise对象
 * 也就是说next()返回的 value 属性是一个Thunk函数或者Promise对象
 * 等待返回真正的值,而done属性还是同步产生
 * 例如:
 */

let idMaker3 = function () {
    let index = 0
    return {
        next: function () {
            return {
                value: new Promise((resolve, reject) => {
                    setTimeout(() => {
                        resolve(index++)
                    }, 1000)
                }),
                done: false
            }
        }
    }
}

const it2 = idMaker3()

it2.next().value.then(res => { console.log(res) }) // 
it2.next().value.then(res => { console.log(res) }) // 
it2.next().value.then(res => { console.log(res) }) // 

/**
 * 但其实就算这样写 看起来也怪怪的
 * 现在引入了 异步遍历接口 asyncIterator
 */

console 命令行工具 X clear

                    
>
console