伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

Node.js 中的异步迭代器

来源:本站原创 浏览:46次 时间:2023-07-07
Node.js 中的异步迭代器

疯狂的技术宅 前端先锋

从 Node.js v10.0.0 开始,异步迭代器就出现中了,最近它们在社区中的吸引力越来越大。在本文中,我们将讨论异步迭代器的作用,还将解决它们可能用于什么目的的问题。

什么是异步迭代器

那么什么是异步迭代器?它们实际上是以前可用的迭代器的异步版本。当我们不知道迭代的值和最终状态时,可以使用异步迭代器,最终我们得到可以解决 {value:any,done:boolean} 对象的 promise。我们还获得了 for-await-of 循环,以帮助我们循环异步迭代器。就像 for-of 循环是针对同步迭代器一样。

 1const asyncIterable = [1, 2, 3]; 2asyncIterable[Symbol.asyncIterator] = async function*() { 3  for (let i = 0; i < asyncIterable.length; i++) { 4    yield { value: asyncIterable[i], done: false } 5  } 6  yield { done: true }; 7}; 8 9(async function() {10  for await (const part of asyncIterable) {11    console.log(part);12  }13})();

与常规的 for-of 循环相反,for-await-of 循环将会 等待它收到的每个 promise 解析后再继续执行下一个。

除了流,当前没有太多支持异步迭代的结构,但是可以将符号手动添加到任何可迭代的结构中,如此处所示。

作为异步迭代器流

异步迭代器在处理流时非常有用。可读流、可写流、双工流和转换流都支持异步迭代器。

 1async function printFileToConsole(path) { 2  try { 3    const readStream = fs.createReadStream(path, { encoding: 'utf-8' }); 4 5    for await (const chunk of readStream) { 6      console.log(chunk); 7    } 8 9    console.log('EOF');10  } catch(error) {11    console.log(error);12  }13}

如果以这种方式编写代码,则不必通过迭代来获取每个数据块时监听 data 和 end 事件,并且 for-await-of 循环随着流本身结束而结束。

调用有分页功能的 API

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

 1const https = require('https'); 2 3function homebrewFetch(url) { 4  return new Promise(async (resolve, reject) => { 5    const req = https.get(url, async function(res) { 6      if (res.statusCode >= 400) { 7        return reject(new Error(`HTTP Status: ${res.statusCode}`)); 8      } 910      try {11        let body = '';1213        /*14          代替 res.on 侦听流中的数据,15          我们可以用 for-await-of,并附加 data chunk16          到响应主体的其余部分17        */18        for await (const chunk of res) {19          body += chunk;20        }2122        // 处理没有 body 的情况23        if (!body) resolve({});24        // 我们需要解析正文以获取 json,因为它是一个字符串25        const result = JSON.parse(body);26        resolve(result);27      } catch(error) {28        reject(error)29      }30    });3132    await req;33    req.end();34  });35}

我们将向 Cat API 发出请求,以 10 张为一组获取一些猫的图片。我们还将在请求之间添加 7 秒的延迟,最大页面数为5,以避免导致 cat API 过载。

我们还将在请求和最大页数之间添加 7 秒钟的延迟5个以避免猫cat API重载,因为那将是灾难性的。

 1function fetchCatPics({ limit, page, done }) { 2  return homebrewFetch(`https://api.thecatapi.com/v1/images/search?limit=${limit}&page=${page}&order=DESC`) 3    .then(body => ({ value: body, done })); 4} 5 6function catPics({ limit }) { 7  return { 8    [Symbol.asyncIterator]: async function*() { 9      let currentPage = 0;10      // Stop after 5 pages11      while(currentPage < 5) {12        try {13          const cats = await fetchCatPics({ currentPage, limit, done: false });14          console.log(`Fetched ${limit} cats`);15          yield cats;16          currentPage ++;17        } catch(error) {18          console.log('There has been an error fetching all the cats!');19          console.log(error);20        }21      }22    }23  };24}2526(async function() {27  try {28    for await (let catPicPage of catPics({ limit: 10 })) {29      console.log(catPicPage);30      // Wait for 7 seconds between requests31      await new Promise(resolve => setTimeout(resolve, 7000));32    }33  } catch(error) {34    console.log(error);35  }36})()

这样,我们就会每隔 7 秒钟自动取回一整页的猫图片,以供欣赏。

一种更常见的在页面之间导航的方法是实现 next 和 previous 方法并将它们公开为控件:

 1function actualCatPics({ limit }) { 2  return { 3    [Symbol.asyncIterator]: () => { 4      let page = 0; 5      return { 6        next: function() { 7          page++; 8          return fetchCatPics({ page, limit, done: false }); 9        },10        previous: function() {11          if (page > 0) {12            page--;13            return fetchCatPics({ page, limit, done: false });14          }15          return fetchCatPics({ page: 0, limit, done: true });16        }17      }18    }19  };20}2122try {23    const someCatPics = actualCatPics({ limit: 5 });24    const { next, previous } = someCatPics[Symbol.asyncIterator]();25    next().then(console.log);26    next().then(console.log);27    previous().then(console.log);28} catch(error) {29  console.log(error);30}

如你所见,当你要获取数据页面或在应用程序的 UI 上进行无限滚动等操作时,异步迭代器将会非常有用。

这些功能已经在浏览器中使用了一段时间,在 Chrome v63+、 Firefox v57+ 和 Safari v11.1 中可用。但是当前在 IE 和 Edge 中不可用。

你是否对使用异步迭代器有什么新想法?你已经在程序中使用它们了吗?请在留言中告诉我。

原文链接

https://blog.risingstack.com/async-iterators-in-node-js/

  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net