ホームページ  >  記事  >  ウェブフロントエンド  >  Node.jsの非同期イテレータとその使い方を詳しく解説

Node.jsの非同期イテレータとその使い方を詳しく解説

青灯夜游
青灯夜游転載
2021-03-23 10:09:171878ブラウズ

この記事では、Node.js の非同期イテレーターについて紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

Node.jsの非同期イテレータとその使い方を詳しく解説

バージョン 10.0.0 以降、非同期イテレータが Node に登場しました。この記事では、非同期イテレータの役割とその使用方法について説明します。

非同期イテレータとは

非同期イテレータは、実際には以前のイテレータの非同期バージョンです。非同期反復子は、反復の値と最終状態がわからない場合に使用できます。 2 つの違いは、取得した Promise が最終的に通常の { value: any, none: boolean } オブジェクトに分解されることです。さらに、for-await- を介してループできることです。 of は非同期反復子を処理します。 for-of ループと同様に、反復子を同期するためにループが使用されます。 [関連する推奨事項: "nodejs チュートリアル "]

const asyncIterable = [1, 2, 3];
asyncIterable[Symbol.asyncIterator] = async function*() {
  for (let i = 0; i < asyncIterable.length; i++) {
    yield { value: asyncIterable[i], done: false }
  }
  yield { done: true };
};

(async function() {
  for await (const part of asyncIterable) {
    console.log(part);
  }
})();

は、通常の for-of ループ、`for-await-of## の逆です。 # ループ 受信した各 Promise が解決されるまで待機してから、次の Promise に進みます。

ストリームのほかに、非同期反復をサポートする構造はありませんが、

asyncIterator シンボルは任意の反復可能な構造に手動で追加できます。

ストリームでの非同期イテレータの使用

非同期イテレータは、ストリームを処理するときに非常に便利です。読み取り可能ストリーム、書き込み可能ストリーム、二重ストリーム、および変換ストリームはすべて、

asyncIterator シンボルでマークされます。

async function printFileToConsole(path) {
  try {
    const readStream = fs.createReadStream(path, { encoding: &#39;utf-8&#39; });

    for await (const chunk of readStream) {
      console.log(chunk);
    }

    console.log(&#39;EOF&#39;);
  } catch(error) {
    console.log(error);
  }
}

この方法でコードを作成すると、データの各チャンクを反復処理するときに

end および data イベントをリッスンする必要がなくなります。 for-await-of ループは、ストリームが終了すると終了します。

ページネーションを使用する API の場合

非同期反復を通じてページネーションを使用するソースからデータを簡単に取得することもできます。この機能を実現するには、Node https リクエスト メソッドによって提供されるストリームから応答本文を再構築する方法も必要です。 https リクエストとレスポンスはどちらもノード内のストリームであるため、ここでも非同期イテレータを使用できます:

const https = require(&#39;https&#39;);

function homebrewFetch(url) {
  return new Promise(async (resolve, reject) => {
    const req = https.get(url, async function(res) {
      if (res.statusCode >= 400) {
        return reject(new Error(`HTTP Status: ${res.statusCode}`));
      }

      try {
        let body = '';

        /*
          代替 res.on 侦听流中的数据,
          可以使用 for-await-of,
          并把数据块附加到到响应体的剩余部分
        */
        for await (const chunk of res) {
          body += chunk;
        }
    
        // 处理响应没有响应体的情况
        if (!body) resolve({});
        // 需要解析正文来获取 json,因为它是一个字符串
        const result = JSON.parse(body);
        resolve(result);
      } catch(error) {
        reject(error)
      }
    });

    await req;
    req.end();
  });
}
コードは、Cat API (https://thecatapi.com/) にリクエストを行うことでいくつかの猫を取得します。の。また、cat API への過剰かつ頻繁なアクセスは非常に非倫理的であるため、これを防ぐために 7 秒の遅延も追加されました。

function fetchCatPics({ limit, page, done }) {
  return homebrewFetch(`https://api.thecatapi.com/v1/images/search?limit=${limit}&page=${page}&order=DESC`)
    .then(body => ({ value: body, done }));
}

function catPics({ limit }) {
  return {
    [Symbol.asyncIterator]: async function*() {
      let currentPage = 0;
      // 5 页后停止
      while(currentPage < 5) {
        try {
          const cats = await fetchCatPics({ currentPage, limit, done: false });
          console.log(`Fetched ${limit} cats`);
          yield cats;
          currentPage ++;
        } catch(error) {
          console.log(&#39;There has been an error fetching all the cats!&#39;);
          console.log(error);
        }
      }
    }
  };
}

(async function() {
  try {
    for await (let catPicPage of catPics({ limit: 10 })) {
      console.log(catPicPage);
      // 每次请求之间等待 7 秒
      await new Promise(resolve => setTimeout(resolve, 7000));
    }
  } catch(error) {
    console.log(error);
  }
})()
このようにして、7 秒ごとに 1 ページ全体の猫の写真が自動的に取得されます。

ページ間を移動するより一般的な方法は、

next メソッドと previous メソッドを実装し、それらをコントロールとして公開することです:

function actualCatPics({ limit }) {
  return {
    [Symbol.asyncIterator]: () => {
      let page = 0;
      return {
        next: function() {
          page++;
          return fetchCatPics({ page, limit, done: false });
        },
        previous: function() {
          if (page > 0) {
            page--;
            return fetchCatPics({ page, limit, done: false });
          }
          return fetchCatPics({ page: 0, limit, done: true });
        }
      }
    }
  };
}

try {
    const someCatPics = actualCatPics({ limit: 5 });
    const { next, previous } = someCatPics[Symbol.asyncIterator]();
    next().then(console.log);
    next().then(console.log);
    previous().then(console.log);
} catch(error) {
  console.log(error);
}
As you Asご覧のとおり、非同期イテレータは、データのページをフェッチしたり、プログラムの UI で無限スクロールなどを実行したりする場合に非常に役立ちます。

これらの機能は、Chrome 63、Firefox 57、および Safari 11.1 で利用できます。

非同期反復子がどこで使用できるかまだ思いつきますか?以下にメッセージを残してください。

プログラミング関連の知識について詳しくは、

プログラミング ビデオをご覧ください。 !

以上がNode.jsの非同期イテレータとその使い方を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。