关于javascript:js异步迭代器async-Iterator

49次阅读

共计 3584 个字符,预计需要花费 9 分钟才能阅读完成。

异步迭代器(async Iterator)

  1. 同步迭代器
  2. 异步迭代器
  3. for await…of
  4. 异步生成器函数
  5. yield* 语句

1. 同步迭代器

  • 一般的迭代器生成函数在被调用后会返回一个迭代器对象,能够去调用迭代器上的 next 办法
  • next 办法一旦执行,就必须同步地失去一个状态对象,{value,done}

    // 迭代器生成函数
    function makeIterator(arr) {
      var nextIndex = 0;
      return {next() {
              return nextIndex < arr.length ?
                  {value: arr[nextIndex++], done: false } :
                  {value: undefined, done: true}
          }
      }
    }
    // 调用并遍历
    const arr = [1]
    let iter = makeIterator(arr)
    console.log(iter.next()) //{value: 1, done: false}
    console.log(iter.next());//{value: undefined, done: true}

2. 异步迭代器

让 next 返回的 value 是一个 Promise 对象,用 then 链式解决

// 迭代器生成函数
function makeIterator(arr) {
    var nextIndex = 0;
    let delay = 4000
    return {next() {
            let res = nextIndex < arr.length ?
                {value: new Promise(resolve => setTimeout(() => resolve(arr[nextIndex++]), delay -= 1000)),
                    done: false
                }
                : {value: undefined, done: true}
            return res
        }
    }
}
// 调用并遍历
const arr = [1, 2]
let iter = makeIterator(arr)
iter.next().value.then(val => console.log(val)) //1
iter.next().value.then(val => console.log(val));//2
iter.next().value.then(val => console.log(val));//undefined

这种办法只是让 value 异步执行,done 的值并不是异步产生的,并且执行了流程不清晰,语义比拟绕

next 间接返回一个 Promise,用 then 的链式解决异步

// 迭代器生成函数
function asyncIterator(arr) {
    var nextIndex = 0
    return {[Symbol.asyncIterator]() {
            return {next() {if (nextIndex < arr.length) {
                        return new Promise(resolve => {setTimeout(() => resolve({value: arr[nextIndex++], done: false }), 1000)
                        })
                    } else {return { value: undefined, done: true}
                    }
                }
            }
        }
    }
}
// 链式执行
const asyncIterable = asyncIterator([1, 2])
const asyncIter = asyncIterable[Symbol.asyncIterator]()
asyncIter
    .next()
    .then(val1 => {console.log(val1);
        return asyncIter.next()})
    .then(val2 => {console.log(val2);
        return asyncIter.next()})
    .then(val3 => {console.log(val3);
    })

//{value: 1, done: false}
//{value: 2, done: false}
//{value: undefined, done: true}

既然 asyncIter 返回的是一个 Promise,那么执行能够用 async 改写,能失去统一的后果

async function runner() {const asyncIterable = asyncIterator([1, 2])
    const asyncIter = asyncIterable[Symbol.asyncIterator]()
    let val1 = await asyncIter.next()
    console.log(val1);
    console.log(await asyncIter.next());
    console.log(await asyncIter.next());
}

3 for await…of

依据下面的迭代器生成函数,Symbol.asyncIterator 是一个异步迭代器的接口,返回一个迭代器对象,能够用 for await…of 去遍历这个接口

async function runner() {for await (const i of asyncIterator([1, 2])) {console.log(i);
    }
}
runner()
//1
//2
  • asyncIterator([1, 2])返回一个 对象 ,这个对象领有 异步迭代器接口,能返回一个异步迭代器对象
  • 这个对象的异步迭代器的 next 办法被 for…of 循环 主动调用 会失去一个Promise 对象
  • await 用来解决这个 Promise 对象,在 resolve 之后 把失去的值 i 传入for…of 的循环体

遍历出错会终止 for await…of,并报错
能够将 for await..of 放在 try 中,用 catch 捕捉谬误

4. 异步生成器函数

同步的生成器函数会生成一个同步迭代器,那么异步生成器则 生成 异步迭代器
作用
Generator 函数解决同步操作和异步操作时,可能应用同一套接口

特点
异步生成器函数就是 async 和 Generator 的联合

function promise(data, delay) {
    return new Promise(resolve => {setTimeout(() => {resolve(data)
        }, delay)
    })
}
function printHello() {return promise("Hello", 1000)
}
function printWorld() {return promise("World", 1000)
}
async function* gene() {yield printHello()
    yield printWorld()}
let iter = gene()
iter.next()
    .then(val => { console.log(val); })//{value:"Hello",done:false}
  • 异步的生成器函数返回一个迭代器对象,调用 next 办法,返回的是一个Promise,用 then 能取到状态对象
  • 同步的生成器函数返回一个迭代器对象,调用 next 办法,间接返回 状态对象,状态对象中的 value 是一个 Promise
  • 应用 for await…of 能够异步的遍历同步迭代器,然而只有 value 是异步的,done 的生成依然是同步的

    async function runner() {for await (const i of iter) {console.log(i);
      }
    }
    runner()

    不论 Generator 函数前是否有 async 都会别离提早 1000ms 打印 Hello 与 World

await 和 yield 能够同时呈现在异步 Generator 函数中

async function* readLines(path) {let file = await fileOpen(path);

  try {while (!file.EOF) {yield await file.readLine();
    }
  } finally {await file.close();
  }
}

await 前面的操作返回一个 Promise 对象,将内部操作产生的值输出函数外部
yield 命令会返回一个 Promise,作为每个 next 暂停的地位,将函数外部的值输入

  • async 函数和异步 Generator 函数都是对异步操作的封装
  • async 函数自带执行器
  • 异步 Generator 函数能够用for await…of 去遍历

函数就能够分为 四类

  1. 一般函数
  2. async 函数
  3. Generator 函数
  4. 异步 Generator 函数

5. yield* 语句

yield* 后能够跟一个 Generator 函数,将其语句开展到异步生成器内

function* gene1() {
    yield 'a'
    yield 'b'
    console.log(0);
}
async function* gene2() {yield* gene1()
    yield 'c';
}
async function runner() {for await (const i of gene2()) {console.log(i);
    }
}
runner()
//"a"
//"b"
//0
//"c"

正文完
 0