Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >结合异步迭代器实现 Node.js 流式数据复制

结合异步迭代器实现 Node.js 流式数据复制

作者头像
五月君
发布于 2021-09-27 02:37:05
发布于 2021-09-27 02:37:05
65500
代码可运行
举报
文章被收录于专栏:Nodejs技术栈Nodejs技术栈
运行总次数:0
代码可运行

实现可读流到可写流数据复制,就是不断的读取->写入这个过程,那么你首先想到的是不是下面这样呢?代码看似很简单,结果却是很糟糕的,没有任何的数据积压处理。如果读取的文件很大了,造成的后果就是缓冲区数据溢出,程序会占用过多的系统内存,拖垮服务器上的其它应用,如果不明白的回顾下这篇文章 Node.js Stream 背压 — 消费端数据积压来不及处理会怎么样?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 糟糕的示例,没有数据积压处理
readable.on('data', data => {
  writable.write(data)
});

类似以上的需求,推荐你用 pipe() 方法以流的形式完成数据的复制

作为学习,结合异步迭代器以一种简单的方式实现一个类似于 pipe 一样的方法完成数据源到目标源的数据复制。

数据写入方法实现

_write 方法目的是控制可写流的数据写入,它返回一个 Promise 对象,如果可写流的 dest.write() 方法返回 true,表示内部缓冲区未满,继续写入。

当 dest.write() 方法返回 false 表示向流中写入数据超过了它所能处理的最大能力限制,此时暂停向流中写入数据,直到 drain 事件触发,表示缓冲区中的数据已排空了可以继续写入,再将 Promise 对象变为解决。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function _write(dest, chunk) {
  return new Promise(resolve => {
    if (dest.write(chunk)) {
      return resolve(null);
    }

    dest.once('drain', resolve);
  })  
}

结合异步迭代器实现

异步迭代器使从可读流对象读取数据变得更简单,异步的读取数据并调用我们封装的 _write(chunk) 方法写入数据,如果缓冲区空间已满,这里 await _write(dest, chunk) 也会等待,当缓冲区有空间可以继续写入了,再次进行读取 -> 写入。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myCopy(src, dest) {
  return new Promise(async (resolve, reject) => {
    dest.on('error', reject);

    try {
      for await (const chunk of src) {
        await _write(dest, chunk);
      }
      resolve();
    } catch (err) {
      reject(err);
    }
  });
}

使用如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const readable = fs.createReadStream('text.txt');
const writable = fs.createWriteStream('dest-text.txt');
await myCopy(readable, writable);

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Nodejs技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Node.js--Stream 1. 概述2. Readable Stream(可读流)3. Writable Stream(可写流)4. 流模式(objectMode )5. 缓冲(highWa
  流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface)。 stream 模块提供了基础的 API 。使用这些 API 可以很容易地来构建实现流接口的对象。
菜的黑人牙膏
2019/01/21
1.6K0
Nodejs Stream pipe 的使用与实现原理分析
通过流我们可以将一大块数据拆分为一小部分一点一点的流动起来,而无需一次性全部读入,在 Linux 下我们可以通过 | 符号实现,类似的在 Nodejs 的 Stream 模块中同样也为我们提供了 pipe() 方法来实现。
五月君
2020/05/19
5.9K0
彻底掌握 Node.js 四大流,解决爆缓冲区的“背压”问题
其实 IO 也就是搬东西,包括网络的 IO、文件的 IO,如果数据量少,那么直接传送全部内容就行了,但如果内容特别多,一次性加载到内存会崩溃,而且速度也慢,这时候就可以一部分一部分的处理,这就是流的思想。
神说要有光zxg
2021/09/03
6310
彻底掌握 Node.js 四大流,解决爆缓冲区的“背压”问题
解析Node.js 中的 Stream(流)
流(Stream)是驱动 Node.js 应用的基础概念之一。它是数据处理方法,用于按顺序将输入读写到输出中。
conanma
2022/01/05
2.8K0
Node.js Stream 背压 — 消费端数据积压来不及处理会怎么样?
Stream 在 Node.js 中是一个被广泛应用的模块,流的两端可读流、可写流之间通过管道链接,通常写入磁盘速度是低于读取磁盘速度的,这样管道的两端就会产生压力差,就需要一种平衡的机制,使得平滑顺畅的从一个端流向另一个端。
五月君
2021/08/12
1.2K0
Node.js Stream 背压 — 消费端数据积压来不及处理会怎么样?
Node.js Stream - 进阶篇
在构建较复杂的系统时,通常将其拆解为功能独立的若干部分。这些部分的接口遵循一定的规范,通过某种方式相连,以共同完成较复杂的任务。譬如,shell通过管道|连接各部分,其输入输出的规范是文本流。 在Node.js中,内置的Stream模块也实现了类似功能,各部分通过.pipe()连接。 上篇(基础篇)主要介绍了Stream的基本概念和用法,本篇将深入剖析背后工作原理,重点是如何实现流式数据处理和back pressure机制。 数据生产和消耗的媒介 为什么使用流取数据 下面是一个读取文件内容的例子: cons
美团技术团队
2018/03/12
1.7K0
Node.js Stream - 进阶篇
[译] 你所需要知道的关于 Node.js Streams 的一切
https://medium.freecodecamp.org/node-js-streams-everything-you-need-to-know-c9141306be93
五月君
2020/02/11
8140
[译] 你所需要知道的关于 Node.js Streams 的一切
2020-6-8-理解node中的stream的背压机制
使用合适的压缩算法能够有效减少请求文件的大小,从而减少网络中的数据传输量,提升响应速度。
黄腾霄
2020/06/10
7170
Node.js 流编程
假如我们要读取一份特别庞大的文件,这份文件有好几个 GB 大小,这种情况下如果使用缓冲模式是相当糟糕的,而且 V8 引擎对缓冲区的尺寸是有限制的,你可能根本没办法分配一个高达好几 GB 的缓冲区,因此有可能还谈不到物理内存耗尽的问题,你在分配缓冲区的这个环节就已经被卡住了。
多云转晴
2024/01/21
2550
[译]关于Node.js streams你需要知道的一切
Node.js的stream模块是有名的应用困难,更别说理解了。那现在可以告诉你,这些都不是问题了。
frontoldman
2019/09/02
1.2K0
[译]关于Node.js streams你需要知道的一切
巧妙复制一个流
实际业务中可能出现重复消费一个可读流的情况,比如在前置过滤器解析请求体,拿到body进行相关权限及身份认证;认证通过后框架或者后置过滤器再次解析请求体传递给业务上下文。因此,重复消费同一个流的需求并不奇葩,这类似于js上下文中通过 deep clone一个对象来操作这个对象副本,防止源数据被污染。
欲休
2018/09/14
4460
一篇文章弄明白Node.js与二进制数据流
二进制数据就像上图一样,由0和1来存储数据。普通的十进制数转化成二进制数一般采用"除2取余,逆序排列"法,用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为小于1时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。例如,数字10转成二进制就是1010,那么数字10在计算机中就以1010的形式存储。
用户6835371
2021/06/01
3.6K0
一篇文章弄明白Node.js与二进制数据流
node中的Stream-Readable和Writeable解读
在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream。Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream、Reader、OutputStream、Writer,其中InputStream和OutputStream类针对字节数据进行读写;Reader和Writer针对字符数据读写。同时Java中有多种针对这四种类型的扩展类,如节点流、缓冲流和转换流等。比较而言,node中Stream类型也和Java中的类似,同样提供了支持字节和字符读写的R
欲休
2018/03/15
1.2K0
node中的Stream-Readable和Writeable解读
Node.js Stream - 基础篇
背景 在构建较复杂的系统时,通常将其拆解为功能独立的若干部分。这些部分的接口遵循一定的规范,通过某种方式相连,以共同完成较复杂的任务。譬如,shell通过管道|连接各部分,其输入输出的规范是文本流。 在Node.js中,内置的Stream模块也实现了类似功能,各部分通过.pipe()连接。 鉴于目前国内系统性介绍Stream的文章较少,而越来越多的开源工具都使用了Stream,本系列文章将从以下几方面来介绍相关内容: 流的基本类型,以及Stream模块的基本使用方法。 流式处理与back pressure的
美团技术团队
2018/03/12
1.1K0
Node.js Stream - 基础篇
如何深入理解 Node.js 中的流(Streams)
在本文中,我们将探讨Node.js中的流概念,了解可用的不同类型的流(可读流、可写流、双工流和转换流),并讨论有效处理流的最佳实践。
前端达人
2023/08/31
7180
如何深入理解 Node.js 中的流(Streams)
NodeJS模块研究 - stream
构建复杂程序的时候,通常会将系统拆解成若干功能,这些功能的之间的接口遵循一定的规范,以实现组合连接,共同完成复杂任务。例如管道运算符 | 。
心谭博客
2020/04/21
1K0
Node.js 中的异步迭代器
从 Node.js v10.0.0 开始,异步迭代器就出现中了,最近它们在社区中的吸引力越来越大。在本文中,我们将讨论异步迭代器的作用,还将解决它们可能用于什么目的的问题。
疯狂的技术宅
2020/05/11
1.8K0
Node.js 中的异步迭代器
Node.js 流源码解读之可读流
1. 基本概念 1.1. 流的历史演变 流不是 Node.js 特有的概念。它们是几十年前在 Unix 操作系统中引入的,程序可以通过管道运算符(|)对流进行相互交互。 在基于 Unix 系统的 MacOS 以及 Linux 中都可以使用管道运算符(|),它可以将运算符左侧进程的输出转换成右侧的输入。 在 Node 中,我们使用传统的 readFile 去读取文件的话,会将文件从头到尾都读到内存中,当所有内容都被读取完毕之后才会对加载到内存中的文件内容进行统一处理。 这样做会有两个缺点: 内存方面:占用大量
用户1097444
2022/06/29
2.2K0
Node.js 流源码解读之可读流
Node中的流
stream是数据集合,与数组、字符串差不多。但stream不一次性访问全部数据,而是一部分一部分发送/接收(chunk式的),所以不必占用那么大块内存,尤其适用于处理大量(外部)数据的场景
ayqy贾杰
2019/06/12
2.4K1
Node中的流
一文学会 Node.js 中的流[每日前端夜话0xF4]
用 Dominic Tarr 的话来说:“流是 Node 中最好的,也是最容易被误解的想法。”即使是 Redux 的创建者和 React.js 的核心团队成员 Dan Abramov 也害怕 Node 流。
疯狂的技术宅
2019/12/11
2.5K0
相关推荐
Node.js--Stream 1. 概述2. Readable Stream(可读流)3. Writable Stream(可写流)4. 流模式(objectMode )5. 缓冲(highWa
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验