stream流定义及使用方法

lxf2023-03-18 17:51:01

本文带大家一起详尽理解一下Nodejs里的stream流控制模块,介绍一下stream流定义及使用方法,希望能帮助到大家!

stream流定义及使用方法

stream流控制模块,是Node中十分最核心的一个控制模块,其他板块如fs、http等都是基于流stream模块案例

但对于大多数前面小白在初入行Node的学习的过程中,针对流的定义和使用还不太好清楚的了解,毕竟在前端的工作上好像非常少有有关"流"解决有关的应用。

1. 流,是啥?

纯粹“流”这字,大家容易产生水流量,流动性等定义。

官方网界定:流,主要是用于在 Node.js 中解决流数据的抽象接口

从官方定位中,我们不难发现:

  • 流,是Node所提供的一种建立模型的一种手段
  • 流,是Node中的一种抽象接口

准确的了解,流,可以理解为数据流分析,它是一种用于传送数据的方法,在一个程序中,流,是一种规范有序,有起点与终点的数据流分析。

导致对于stream流不是很好的接受的主要原因就是,它是一种抽象概念。

2. 流,的实际适用场景

为了能使我们可以很清楚的了解stream控制模块,我们先来以实际的应用场景而言明stream控制模块有什么实践应用的地方。

stream流,在Node中主要应用在海量数据解决的需要上,如fs对大文件的读取和写入、http请求响应、文件信息缩小、数据库的数据加密/破译等应用。

stream流定义及使用方法

大家之上面的图片表明流的应用,塑料水桶可以理解为数据库,蓄水池可以理解为数据信息总体目标,中间连接管道,大家可以理解为数据流分析,根据数据流分析管路,数据信息从数据库流入数据信息总体目标。

3. 流的归类

在Node中,流被分为4类:能读流,应写流,全双工流,变换流。

  • Writable: 能够载入数据库的流
  • Readable: 可以从中获取数据的流
  • Duplex: ReadableWritable 的流
  • Transform: 还可以在载入和获取数据时改动或转换数据的 Duplex

每一个流全是 EventEmitter 的案例。即我们通过事件机制监视数据流分析的改变。

4. 数据模式和缓存区

在加强学习4类流的实际应用以前,我们需要理解两回事数据模式缓存区,有助于我们在今后流学习的过程中更好的理解。

4.1 数据模式

Node.js API 建立的全部流都仅对字符串数组Buffer(或 Uint8Array)目标来操作。

4.2 缓存区

WritableReadable 流也将文件存储在外部缓冲区域(buffer)中。

可抗震的信息量在于发送给流的对象highWaterMark 选择项, 对于一般的流,highWaterMark 选择项特定字节数总数;对在目标模式中操控的流,highWaterMark选择项特定目标总数。

highWaterMark 选择项是阀值,而非限定:它明确了流在终止要求大量数据信息以前缓存的信息量。

当完成启用 stream.push(chunk) 时,数据缓存在 Readable 流中。 假如流的顾客并没有启用 stream.read(),则数据信息会一直停留在外部序列中,直至被消费。

一旦内部结构载入缓冲区域的总体尺寸做到 highWaterMark 指定阀值,则流将暂时中止从底层网络资源获取数据,直至能够交易现阶段缓存的信息

当反复启用 writable.write(chunk) 方式时,数据信息会存储在 Writable 流中。

5. 能读流

5.1 流载入的流动与中止

Readable 流以两种模式之一高效地运作:流动性和中止。

  • 流动模式:从操作系统最底层获取数据并push()到缓存区,做到highWaterMark后 push() 会回到 false,网络资源终止流入缓存区,并开启data事情消费报告。

  • 中止方式:每一个Readable流都以Paused中止方式逐渐,务必显式启用stream.read()方式来从流中获取数据。每一次数据信息做到缓存区都是会开启一次 readable 事情,其实就是每一次 push() 都是会开启 readable。

  • 中止双模式到流动模式的形式:

    • 加上data事情返回值
    • 启用stream.resume()方式
    • 启用stream.pipe()方式将数据发送到 Writable
  • 流动性双模式到中止方式的方法:

    • 要是没有管路总体目标,也可通过启用 stream.pause() 方式。
    • 若是有管路总体目标,则删除所有管路总体目标。 能通过启用 stream.unpipe()方式删掉好几个管路总体目标。

5.2 能读流常见实例

import path from 'path';
import fs, { read } from 'fs';

const filePath = path.join(path.resolve(), 'files', 'text.txt');

const readable = fs.createReadStream(filePath);
// 如果采用 readable.setEncoding() 方法为流特定了默认设置编号,则监控器调整将db块做为字符串数组传到;不然数据信息将成为 Buffer 传到。
readable.setEncoding('utf8');
let str = '';

readable.on('open', (fd) => {
  console.log('逐渐读取文件')
})
// 每每流将db块的使用权移交顾客时,往往会开启 'data' 事情
readable.on('data', (data) => {
  str  = data;
  console.log('载入到数据信息')
})
// 方式可能导致处在流动模式的流终止开启 'data' 事情,转换到中止方式。 一切可利用的数据信息也将保留在内部结构缓冲区域中。
readable.pause();
// 方式使被显式中止的 Readable 流修复开启 'data' 事情,将流转换到流动模式。
readable.resume();
// 当启用 stream.pause() 而且 readableFlowing 并不是 false 时,往往会开启 'pause' 事情。
readable.on('pause', () => {
  console.log('载入中止')
})
// 当启用 stream.resume() 而且 readableFlowing 并不是 true 时,往往会开启 'resume' 事情。
readable.on('resume', () => {
  console.log('再次流动性')
})
// 当流中没有那么多数据信息能够购物时,往往会开启 'end' 事情。
readable.on('end', () => {
  console.log('文件读取结束');
})
// 当流以及一切最底层网络资源(比如文件描述符)已停用时,往往会开启 'close' 事情。
readable.on('close', () => {
  console.log('关掉文件读取')
})
// 将 destWritable 流关联到 readable,使之自动选择到流动模式并把它全部数据推送到关联的 Writable。 数据流分析要被自动管理
readable.pipe(destWriteable)
// 假如最底层流因为最底层内部结构常见故障而难以生成数据,或是当流完成试着消息推送无效数据块时,可能发生这样的事情。
readable.on('error', (err) => {
  console.log(err)
  console.log('文件读取出现错误')
})

6. 应写流

6.1 应写流的流动性与中止

writeable流 与 readable流 还是比较相近的,数据流分析来时,就会直接载入到缓存区,当读取速度比较缓慢或是载入中止时,数据流分析会到缓存区缓存文件下去;

当经营者载入速度过快,把序列池塞满了以后,就容易出现「背压式」,这时候也是需要告知经营者中止制造的,当序列释放出来以后,writable流 能给经营者推送一个 drain 信息,使它全面复工复产。

6.2 应写流实例

import path from 'path';
import fs, { read } from 'fs';

const filePath = path.join(path.resolve(), 'files', 'text.txt');
const copyFile = path.join(path.resolve(), 'files', 'copy.txt');

let str = '';
// 建立能读流
const readable = fs.createReadStream(filePath);
// 如果采用 readable.setEncoding() 方法为流特定了默认设置编号
readable.setEncoding('utf8');

// 建立应写流
const wirteable = fs.createWriteStream(copyFile);
// 编号
wirteable.setDefaultEncoding('utf8');

readable.on('open', (fd) => {
  console.log('逐渐读取文件')
})
// 每每流将db块的使用权移交顾客时,往往会开启 'data' 事情
readable.on('data', (data) => {
  str  = data;
  console.log('载入到数据信息');

  // 载入
  wirteable.write(data, 'utf8');
})

wirteable.on('open', () => {
  console.log('逐渐载入数据信息')
})
// 如果对于 stream.write(chunk) 的启用回到 false,则 'drain' 事情将于适宜再次将它们载入流时开启。
// 即运行数据速度超过读取速度,缓存区放满以后,会中止生产制造着从底层获取数据
// writeable缓存区释放出来以后,会上传一个drain事情让经营者再次载入
wirteable.on('drain', () => {
  console.log('再次载入')
})
// 在启用 stream.end() 方式以后,而且所有数据早已更新到最底层系统软件,则开启 'finish' 事情。
wirteable.on('finish', () => {
  console.log('数据信息载入结束')
})

readable.on('end', () => {
  // 数据读取结束通告应写流
  wirteable.end()
})
// 如在能读流上启用 stream.pipe() 方式将这一应写流导入到其总体目标集时,则开启 'pipe' 事情。
// readable.pipe(destWriteable)
wirteable.on('pipe', () => {
  console.log('管道流建立')
})

wirteable.on('error', () => {
  console.log('数据信息载入出现错误')
})

大量node基本知识,请访问:nodejs 实例教程!!

以上就是关于聊一聊Nodejs中的核心控制模块:stream流控制模块(看一下怎么使用)的具体内容,大量欢迎关注AdminJS其他类似文章!