Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung des asynchronen Iterators von Node.j und seiner Verwendung

Detaillierte Erläuterung des asynchronen Iterators von Node.j und seiner Verwendung

青灯夜游
青灯夜游nach vorne
2021-03-23 10:09:171878Durchsuche

Dieser Artikel stellt Ihnen asynchrone Iteratoren in Node.js vor. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

Detaillierte Erläuterung des asynchronen Iterators von Node.j und seiner Verwendung

Asynchrone Iteratoren sind in Node seit Version 10.0.0 verfügbar. In diesem Artikel besprechen wir die Rolle asynchroner Iteratoren und wo sie verwendet werden können.

Was ist ein asynchroner Iterator?

Asynchrone Iteratoren sind eigentlich asynchrone Versionen früherer Iteratoren. Asynchrone Iteratoren können verwendet werden, wenn wir den Wert und den Endzustand der Iteration nicht kennen. Der Unterschied zwischen den beiden besteht darin, dass das Versprechen, das wir erhalten, schließlich in ein gewöhnliches { value: any, done: boolean -Objekt zerlegt wird. Außerdem kann es for-await- übergeben werden. of Schleife zur Verarbeitung asynchroner Iteratoren. Genauso wie die for-of-Schleife zum Synchronisieren von Iteratoren verwendet wird. [Verwandte Empfehlungen: „nodejs Tutorial{ value: any, done: 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 解析之后再继续执行下一个。

除了流之外,还在还没有什么能够支持异步迭代的结构,但是可以将 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);
  }
}

如果以这种方式写代码,就不需要在通过迭代获取每个数据块时监听 enddata 事件了,并且 for-await-of 循环会随着流的结束而结束。

用于有分页功能的 API

你还可以通过异步迭代从使用分页的源中轻松获取数据。为了实现这个功能,还需要一种从Node https 请求方法提供给的流中重构响应主体的方法。在这里也可以使用异步迭代器,因为 https 请求和响应在 Node 中都是流:

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/)发出请求,来获取一些猫的图片。另外还添加了 7 秒钟的延迟防止对 cat API 的访问过与频繁,因为那样是极其不道德的。

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秒钟自动取回一整页的喵星人图片。

一种更常见的页面间导航的方法可实现 nextprevious"]

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);
}

und normalerweise Im Gegensatz zur for-of-Schleife wartet die `for-await-of-Schleife auf die Auflösung jedes empfangenen Versprechens, bevor sie mit dem nächsten fortfährt.

Außer Streams gibt es keine Struktur, die asynchrone Iteration unterstützen kann, aber das Symbol asyncIterator kann manuell zu jeder iterierbaren Struktur hinzugefügt werden.

Asynchrone Iteratoren für Streams verwenden

Asynchrone Iteratoren sind sehr nützlich, wenn Sie mit Streams arbeiten. Lesbare Streams, beschreibbare Streams, Duplex-Streams und Transformations-Streams sind alle mit dem Symbol asyncIterator gekennzeichnet. rrreeeWenn Sie Ihren Code auf diese Weise schreiben, müssen Sie nicht auf die Ereignisse end und data achten, während Sie jeden Datenblock durchlaufen, und for- Die Await-of-Schleife endet, wenn der Stream endet.

🎜Für APIs mit Paginierung🎜🎜Sie können auch problemlos Daten aus Quellen abrufen, die Paginierung über asynchrone Iteration verwenden. Um diese Funktionalität zu erreichen, benötigen Sie außerdem eine Möglichkeit, den Antworttext aus dem Stream zu rekonstruieren, der von der Knoten-https-Anforderungsmethode bereitgestellt wird. Hier können auch asynchrone Iteratoren verwendet werden, da https-Anfragen und -Antworten beide Streams im Knoten sind: 🎜rrreee🎜Der Code erhält einige Katzenbilder, indem er eine Anfrage an die Cat-API (https://thecatapi.com/) stellt. Außerdem wurde eine Verzögerung von 7 Sekunden hinzugefügt, um übermäßigen und häufigen Zugriff auf die Cat-API zu verhindern, da dies äußerst unethisch wäre. 🎜rrreee🎜Auf diese Weise rufen wir alle 7 Sekunden automatisch eine ganze Seite mit Katzenbildern ab. 🎜🎜Eine gängigere Möglichkeit, zwischen Seiten zu navigieren, besteht darin, die Methoden next und previous zu implementieren und sie als Steuerelemente bereitzustellen: 🎜rrreee🎜Wie Sie sehen können, wann Sie möchten Get Asynchrone Iteratoren können sehr nützlich sein, wenn Sie beispielsweise endlos auf Datenseiten oder in der Benutzeroberfläche eines Programms scrollen. 🎜🎜Diese Funktionen sind in Chrome 63+, Firefox 57+ und Safari 11.1+ verfügbar. 🎜🎜Können Sie sich noch vorstellen, wo asynchrone Iteratoren eingesetzt werden können? Gerne können Sie unten eine Nachricht hinterlassen! 🎜🎜Weitere Kenntnisse zum Thema Programmierung finden Sie unter: 🎜Programmiervideos🎜! ! 🎜

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des asynchronen Iterators von Node.j und seiner Verwendung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen