Web前端关于 Node.js 中的异步迭代器
小职 2021-03-09 来源 :转自:前端先锋 阅读 730 评论 0

摘要:​本文主要介绍了Web前端关于 Node.js 中的异步迭代器,通过具体的内容向大家展现,希望对大家web前端Node.js的学习有所帮助。

本文主要介绍了Web前端关于 Node.js 中的异步迭代器,通过具体的内容向大家展现,希望对大家web前端Node.js的学习有所帮助。

Web前端关于 Node.js 中的异步迭代器

什么是异步迭代器

 

异步迭代器实际上是以前迭代器的异步版本。当我们不知道迭代的值和最终状态时,可以使用异步迭代器。两者不同的地方在于,我们得到的 promise 最终将被分解为普通的 { value: any, done: boolean } 对象,另外可以通过 for-await-of 循环来处理异步迭代器。就像 for-of 循环用于同步迭代器一样。

 

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: 'utf-8' });

 

    for await (const chunk of readStream) {

      console.log(chunk);

    }

 

    console.log('EOF');

  } catch(error) {

    console.log(error);

  }

}

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

 

用于有分页功能的 API

 

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

 

const https = require('https');

 

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('There has been an error fetching all the cats!');

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

 

一种更常见的页面间导航的方法可实现 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);

}

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

 

这些功能在 Chrome 63+、Firefox 57+、Safari 11.1+ 中可用。


我是小职,记得找我

✅ 解锁高薪工作

✅ 免费获取学习教程,开发工具,代码大全,参考书籍

Web前端关于 Node.js 中的异步迭代器

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程