NodeJs IO流

是什么?

把一个东西从 A 搬到 B 该怎么搬呢?

抬起来,移动到目的地,放下不就行了么。

那如果这个东西有一吨重呢?

那就一部分一部分的搬。

其实 IO 也就是搬东西,包括网络的 IO、文件的 IO,如果数据量少,那么直接传送全部内容就行了,但如果内容特别多,一次性加载到内存会崩溃,而且速度也慢,这时候就可以一部分一部分的处理,这就是流的思想。

nodejs 四种流

可写流,可读流,双工流,转换流, 下文只描述了 可写流和可读流 的使用。

流的直观感受

从一个地方流到另一个地方,显然有流出的一方和流入的一方,流出的一方就是可读流(readable),而流入的一方就是可写流(writable)。

背压

但是 read 和 write 都是异步的,如果两者速率不一致呢?

如果 Readable 读入数据的速率大于 Writable 写入速度的速率,这样就会积累一些数据在缓冲区,如果缓冲的数据过多,就会爆掉,会丢失数据。

而如果 Readable 读入数据的速率小于 Writable 写入速度的速率呢?那没关系,最多就是中间有段空闲时期。

这种读入速率大于写入速率的现象叫做"背压",或者"负压"。也很好理解,写入段压力比较大,写不进去了,会爆缓冲区,导致数据丢失。

如何解决

当调用 writable stream 的 write 方法的时候会返回一个 boolean 值代表是写入了目标还是放在了缓冲区:

  • true: 数据已经写入目标
  • false:目标不可写入,暂时放在缓冲区

我们可以判断返回 false 的时候就 pause,然后等缓冲区清空了就 resume:

js 复制代码
const rs = fs.createReadStream(srcFilename);
const ws = fs.createWriteStream(dstFilename);

rs.on('data', function (chunk) {
    if (ws.write(chunk) === false) {
        rs.pause();
    }
});

rs.on('end', function () {
    ws.end();
});

ws.on('drain', function () {
    rs.resume();
});

这样就能达到根据写入速率暂停和恢复读入速率的功能,解决了背压问题。

drain钩子官方解析

Event: 'drain'#

Added in: v0.9.4

If a call to stream.write(chunk) returns false, the 'drain' event will be emitted when it is appropriate to resume writing data to the stream.

也可以用pipe 管道

ini 复制代码
const rs = fs.createReadStream(src);
const ws = fs.createWriteStream(dst);

rs.pipe(ws);

参考链接

神说要有光-# 彻底掌握 Node.js 四大流,解决爆缓冲区的"背压"问题

相关推荐
IT_陈寒13 小时前
为什么你应该学习JavaScript?
前端·人工智能·后端
淇奥714 小时前
【MyBatis-Plus】MyBatis-Plus 学习笔记
后端
_code_bear_14 小时前
OpenSpec CLI 与 OPSX 工作流说明
前端·后端·架构
用户83562907805114 小时前
使用 Python 在 PowerPoint 中添加并控制音频播放
后端·python
用户83562907805114 小时前
使用 Python 在 PowerPoint 中生成并自定义饼图与环形图
后端·python
念何架构之路15 小时前
Go语言常见并发模式
开发语言·后端·golang
Cosolar15 小时前
大模型应用开发面试 • 第4期|A2A、复杂挑战与具身智能
人工智能·后端·面试
迷渡15 小时前
聊一聊 Bun 用 Rust 重写这件事
开发语言·后端·rust
王中阳Go15 小时前
秒杀、分库分表、全链路追踪:一个电商微服务的架构全拆解
后端·go
正儿八经的少年15 小时前
Spring Boot 两种激活配置方式的作用与区别
java·spring boot·后端