Node.js中的异步生成器与异步迭代详解

Node.js中的异步生成器与异步迭代详解

异步迭代

异步迭代可以理解为一种异步操作处理流程,我们通过一个example框架来讲解其中的机制。

假设有这样一种场景,我们需要上传多张图片到远端服务器,并在所有的图片上传完成之后返回一个数组,数组中的每个元素为每一张图片上传成功后返回的结果。我们可以通过以下代码实现:

async function uploadPictures(pictures) {
  const results = [];
  for (const picture of pictures) {
    const result = await uploadPicture(picture);
    results.push(result);
  }
  return results;
}

上面的代码中使用了 for-of 循环来遍历 pictures 数组,每次遍历将图片上传到远端服务器,并将返回的结果 push 到 results 数组中。同时,使用 await 关键字等待每次异步操作完成后才进行下一次循环和操作。

但上面的代码存在一些问题,比如示例中的操作实际上是顺序执行的(同步运行),存在阻塞操作,当上传图片数量过多时,代码会因为阻塞而变得非常慢,降低系统的性能。为了解决这些问题,异步迭代应运而生。

使用异步迭代进行优化:

async function* uploadPictures(pictures) {
  for (const picture of pictures) {
    yield uploadPicture(picture);
  }
}

async function run() {
  const iterator = uploadPictures([1, 2, 3, 4, 5]);
  for await (const result of iterator) {
    console.log(result);
  }
}

上面的代码中,我们使用异步迭代器 async function* 重构了该函数的实现,将其变为一个生成器函数(generator function),其目的是让函数异步迭代图片上传的过程,即:

  1. 使用 yield 将每张图片上传操作返回,将该操作封装在生成器函数中。

  2. 使用异步迭代器遍历生成器函数,循环中的每一次异步操作都实现了异步执行(非阻塞)。

异步生成器

异步生成器是异步迭代的实现基础,它本身就是一个生成器函数,但可以通过 asyncawait 声明异步操作。在生成异步数据时,可以使用 yield 关键字将每个异步返回值返回到迭代器中,而异步操作执行完毕后也可以通过 return 关键字返回值,或者通过 throw 关键字抛出异常。

我们通过一个异步生成器的例子来帮助理解其机制:

async function* generateNumbers() {
  let i = 0;
  while (i < 5) {
    console.log('start');
    yield new Promise(resolve =>
      setTimeout(() => resolve(i++), 1000)
    );
    console.log('end');
  }
}

async function run() {
  const iterator = generateNumbers();
  for await (const number of iterator) {
    console.log(number);
  }
}

上面的代码中,通过异步生成器 generateNumbers() 实现异步生成 0-5 的整数,并使用异步迭代器 for await (const number of iterator) 获取异步生成器生成的每个值,并打印到控制台上。

需要注意的是,在 generateNumbers() 函数中使用了 yield new Promise(resolve => setTimeout(() => resolve(i++), 1000)); 这条语句的作用是暂停异步流程并等待该 Promise 对象的完成,然后再进一步执行下一步操作。

示例说明

异步迭代示例

我们继续使用上面的上传图片的示例来说明异步迭代的使用。

async function* uploadPictures(pictures) {
  for (const picture of pictures) {
    yield uploadPicture(picture);
  }
}

async function run() {
  const iterator = uploadPictures([1, 2, 3, 4, 5]);
  for await (const result of iterator) {
    console.log(result);
  }
}

上面的代码中,uploadPictures() 函数就是一个异步生成器,它将上传每一张图片的操作异步生成,然后使用异步迭代器遍历每次异步操作的结果,并将结果打印到控制台上。

异步生成器示例

我们再来看一个异步生成器示例,实现打印斐波那契数列前 n 项数。

async function* fibonacci(limit) {
  let [prev, curr] = [0, 1];
  for (let i = 0; i < limit; i++) {
    await new Promise(resolve => setTimeout(resolve, 1000));
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

async function run() {
  const iterator = fibonacci(10);
  for await (const number of iterator) {
    console.log(number);
  }
}

上述代码中,我们声明了一个异步生成器函数 fibonacci(),该函数生成了斐波那契数列的前 n 项,每次生成一个数值前会等待一秒钟,然后使用 yield 返回生成数据。最后在 run() 函数中使用异步迭代器遍历生成器函数返回的值,并将每个异步生成的值打印到控制台上。

使用异步生成器和异步迭代器可以更好地管理异步代码及其调度,使得代码更清晰、更可读且更易于调试。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Node.js中的异步生成器与异步迭代详解 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • 详细谈谈NodeJS进程是如何退出的

    当NodeJS进程退出时,会发生以下几个事件: 执行完所有的exit回调函数 事件循环结束 所有未被清理的定时器和Interval函数被清理 通过process.exit()函数强制终止进程 NodeJS进程可以通过以下几种方式退出: 自然退出:所有的任务都完成了,NodeJS自动退出进程。 抛出未被捕捉到的异常:抛出未被捕捉到的异常也会使NodeJS进程退…

    node js 2023年6月8日
    00
  • NodeJS实现自定义流的方法

    Node.js是一个基于Chrome V8引擎的JavaScript运行环境,可以使用它来开发服务器和命令行工具。流(Stream)是Node.js中非常重要的概念,是对提高数据读取和写入效率的一种机制。Node.js提供了一些内置的文件流和网络流,同时还提供了API来自定义流。 自定义流的原理 在Node.js中,流是一种基于事件的API,它具有以下几个特…

    node js 2023年6月8日
    00
  • 单线程JavaScript实现异步过程详解

    单线程JavaScript实现异步过程就是通过事件循环机制实现的。该机制通过回调函数的方式,将需要异步执行的代码推入事件队列,等待主线程空闲时再执行。 具体实现过程如下: 首先,我们需要定义一个函数,它能够接受一个回调函数作为参数,这个回调函数会在异步操作结束后被执行。 function loadData(callback) { // 这里是异步操作的代码,…

    node js 2023年6月8日
    00
  • Nodejs+express+ejs简单使用实例代码

    下面是关于“Nodejs+express+ejs简单使用实例代码”的详细讲解: 什么是Node.js? Node.js是一个基于Chrome V8引擎的JavaScript运行环境,可以实现后台的JavaScript脚本,被广泛应用于Web服务器端的开发。 什么是Express? Express是一个基于Node.js平台的Web应用开发框架,它提供了大量W…

    node js 2023年6月8日
    00
  • Mac平台中编译安装Lua运行环境及Hello Lua实例

    下面是详细的攻略: Mac平台中编译安装Lua运行环境 首先需要在Mac平台上安装Xcode命令行工具,在终端执行以下命令: xcode-select –install 接着,从Lua官网(https://www.lua.org/)下载最新的源代码包,并解压到本地目录中。 在终端进入解压后的目录,执行以下命令编译Lua: make macosx 如果一切顺…

    node js 2023年6月8日
    00
  • 利用node.js爬取指定排名网站的JS引用库详解

    下面是“利用node.js爬取指定排名网站的JS引用库详解”的完整攻略。 一、背景 在网站开发过程中,我们需要引用许多第三方库,如jQuery、Vue.js等常用的JavaScript库。但是,我们如何了解哪些库在我们的网站上使用了?这时候,我们可以通过爬取指定排名网站的JS引用库来获取这些信息。 二、工具与资源 本攻略将使用以下工具和资源来实现目标: No…

    node js 2023年6月8日
    00
  • JavaScript内存管理与闭包实例详解

    JavaScript内存管理与闭包实例详解 什么是JavaScript内存管理? JavaScript在运行时使用动态内存分配。当它需要使用内存时,它会请求所需数量的内存,当它不再使用内存时,它会释放该内存。但是,JavaScript没有提供垃圾回收机制来自动释放不再使用的内存。相反,开发人员需要手动管理内存。这意味着从内存分配到内存释放都是由开发人员掌控的…

    node js 2023年6月8日
    00
  • node.js基于socket.io快速实现一个实时通讯应用

    下面详细讲解“node.js基于socket.io快速实现一个实时通讯应用”的完整攻略。 简介 Socket.io 是一个优秀的跨浏览器的 WebSocket 实现,它解决了 WebSocket 在使用过程中的兼容性问题,并且实现了多种应用级别的实时通信协议。使用 Node.js 和 Socket.io 可以快速实现一个实时通讯应用。 准备 首先,你需要安装…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部