1. 程式人生 > 其它 >JavaScript – Async Iterator & Generator

JavaScript – Async Iterator & Generator

前言

要看懂這篇請先看下面幾篇

JavaScript – Iterator

JavaScript – Generator Function

JavaScript – Promise

JavaScript – 用 Generator 執行非同步函式 & await async

Async Iterator (es2018)

es6 推出的 Iterator + for...of 非常好用, 但是它只能執行同步程式碼. 不支援非同步程式設計.

顧名思義 Async Iterator 就是 Iterator 的 Async 版本. 它支援非同步程式設計.

我們來看看 sync 和 async Iterator 的對比

sync Iterable

const iterable: Iterable<string> = {
  [Symbol.iterator]() {
    let index = 0;
    return {
      next() {
        index++;
        if (index === 10) {
          return {
            done: true,
            value: '',
          };
        }
        return { done: false, value: 'value' + index };
      },
    };
  },
};

for (const value of iterable) { console.log('value', value); }

async Iterable

const asyncIterable: AsyncIterable<string> = {
  [Symbol.asyncIterator]() {
    let index = 0;
    return {
      async next() {
        return new Promise((resolve) => {
          setTimeout(() => {
            index
++; if (index === 10) { resolve({ done: true, value: '', }); } return resolve({ done: false, value: 'value' + index }); }, 1000); }); }, }; }, }; (async () => { const asyncIterator = asyncIterable[Symbol.asyncIterator](); const { value, done } = await asyncIterator.next(); console.log([value, done]); for await (const value of asyncIterable) { console.log('value', value); } })();

和 sync iterable 的區別是

1. 屬性是 Symbol.asyncIterator

2. iterator next 返回的是一個 promise, promise 的返回才是 done 和 value

3. 遍歷的方式是 for await ... of

你可能會認為, sync iterable 也可以返回 promise 丫.

的確. 在 JavaScript – 用 Generator 執行非同步函式 & await async 裡有提到如何用 Generator + Iterator + Promise + 自執行 Generator 來實現非同步程式設計 (async await 語法糖的背後的原理)

它的 iterator next value 返回的就是 promise. 但不要忘了, 還有 done 屬性呢? 這個總不能返回 Promise 了丫. 所以還是有細微區別的. 

Async Generator (es2018)

和 Async Iterator 一樣概念. Generator 也有 Async 版本.

function delayAsync(time: number, value: string) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(value);
    }, time);
  });
}
async function* myGenerator() {
  yield delayAsync(1000, 'a');
  console.log('do something');
  yield delayAsync(1000, 'b');
}
(async () => {
  const asyncIterator = myGenerator();
  for await (const value of asyncIterator) {
    console.log(value);
  }
  // 1000ms after log a
  // do something
  // another 1000ms after log b
})();

和 sync Generator 的區別是

1. async function* 多了 async 關鍵字開頭

2. yield 返回 Promise

3. 可以用 for await...of 遍歷