stream nodejs,node stream

  stream nodejs,node stream

  本文带你详细了解Nodejs中的stream模块,并介绍stream的概念和用法,希望对你有所帮助!

  node.js速度课程简介:进入学习

  流模块是Node中非常核心的模块,其他模块如fs、http都是基于流模块的实例。

  但是大部分前端小白同学在new Node的学习过程中,对于flow的概念和使用仍然没有一个清晰的认识,因为在前端工作中似乎很少有涉及到 flow 处理的应用。

  

1. 流,是什么?

  单纯的“流”这个词,我们很容易产生水流、流量等概念。

  从官方的定义中,我们可以看出:

  Stream是处理Node提供的数据的工具流。它是Node中的一个抽象接口。可以准确理解为数据流。它是一种传输数据的手段。在应用程序中,流是有起点和终点的有序数据流。

  我们对stream理解不好的主要原因是它是一个抽象的概念。

  

2. 流,的具体使用场景

  为了让我们更清楚的了解stream模块,我们先用具体的应用场景来说明stream模块的实际应用。

  Stream,在Node中,主要用于大量的数据处理需求,如fs读写大文件、http请求响应、文件压缩、数据加密/解密等应用。

  我们用上图来说明心流的使用。桶可以理解为数据源,池可以理解为数据目标,中间连接的管道可以理解为数据流。通过数据流管道,数据从数据源流向数据目标。

  

3. 流的分类

  在Node中,流分为四类:可读流、可写流、双工流和转换流。

  Writeable:可以写入数据的流。可读:可以从中读取数据的流。双工:可读和可写流。转换:在读写数据时可以修改或转换数据的双工流。所有流都是EventEmitter的实例。也就是我们可以通过事件机制来监控数据流的变化。

  

4. 数据模式和缓存区

  在深入研究四类流的具体使用之前,我们需要了解两个概念性的数据模式和缓冲区,这将有助于我们在接下来的流学习中有更好的理解。

  4.1 数据模式

  Node.js API创建的所有流只对字符串和缓冲区(或Uint8Array)对象进行操作。

  4.2 缓存区

  可写和可读流都将数据存储在内部缓冲区中。

  可以缓冲的数据量取决于传递给流的构造函数的highWaterMark选项。对于普通流,highWaterMark选项指定总字节数;对于在对象模式下运行的流,highWaterMark选项指定对象的总数。

  highWaterMark选项是一个阈值,而不是一个限制:它指定流在停止请求更多数据之前缓冲的数据量。

  当实现调用stream.push(chunk)时,数据缓存在可读流中。如果流的使用者不调用stream.read(),则数据将留在内部队列中,直到被使用。

  一旦内部读取缓冲区的总大小达到highWaterMark指定的阈值,流将暂时停止从基础资源读取数据,直到它可以使用当前缓冲的数据。

  当重复调用writable.write(chunk)方法时,数据被缓存在可写流中。

  

5. 可读流

  5.1 流读取的流动与暂停

  可读流以两种模式之一有效运行:流和暂停。

  流模式:从系统底层读取数据,并将()推送到缓冲区。当达到highWaterMark时,push()将返回false,资源将停止流向缓冲区,从而触发数据事件来消耗数据。

  暂停模式:所有可读流都以暂停模式启动,并且必须显式调用stream.read()方法来从流中读取数据。每次数据到达缓冲区时,都会触发一个可读事件,即每次push()都会触发可读。

  如何从暂停模式切换到流动模式:

  添加数据事件句柄,调用stream.resume()方法,调用stream.pipe()方法,将数据发送到Writable。如何将流动模式切换到暂停模式:

  如果没有管道目标,则调用stream.pause()方法。如果有管道目标,请删除所有管道目标。通过调用stream.unpipe()方法,可以删除多个管道目标。5.2 可读流常用示例

  从“path”导入路径;

  从“fs”导入fs,{ read };

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

  const readable=fs . createreadstream(file path);

  //如果使用readable.setEncoding()方法为流指定了默认编码,侦听器回调将数据块作为字符串传入;否则,数据将作为缓冲区传入。

  readable . set encoding( utf8 );

  设str=“”;

  readable.on(open ,(fd)={

  Console.log(开始读取文件)

  })

  //只要流将数据块的所有权交给使用者,就会触发“data”事件。

  readable.on(data ,(data)={

  str=数据;

  Console.log(读取数据)

  })

  //该方法将导致流模式中的流停止触发“数据”事件,并切换到暂停模式。任何可用的数据都将保存在内部缓冲区中。

  readable . pause();

  //方法使显式暂停的可读流恢复,并触发“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,这样可以自动切换到flow模式,将其所有数据推送到绑定的Writable。数据流将被自动管理。

  可读管道(可写)

  //如果基础流由于基础内部故障而无法生成数据,或者当流实现试图推送无效数据块时,可能会发生这种情况。

  readable.on(error ,(err)={

  console.log(错误)

  Console.log(“文件读取错误”)

  })

6. 可写流

  6.1 可写流的流动与暂停

  可写流类似于可读流。当数据流到来时,它将被直接写入缓冲区。当写入速度较慢或写入暂停时,数据流将缓存在缓冲区中。

  当生产者写得太快,填满了队列池,就会产生“反压”。这时候就要告诉生产商暂停生产了。当队列被释放时,可写流将向生产者发送排出消息,让其恢复生产。

  6.2 可写流示例

  从“path”导入路径;

  从“fs”导入fs,{ read };

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

  const copy file=path . join(path . resolve(), files , copy . txt );

  设str=“”;

  //创建可读的流

  const readable=fs . createreadstream(file path);

  //如果使用readable.setEncoding()方法为流指定了默认编码

  readable . set encoding( utf8 );

  //创建可写的流

  const wirte able=fs . createwritestream(copy file);

  //编码

  wirte table . setdefaultencoding( utf8 );

  readable.on(open ,(fd)={

  Console.log(开始读取文件)

  })

  //只要流将数据块的所有权交给使用者,就会触发“data”事件。

  readable.on(data ,(data)={

  str=数据;

  Console.log(读取数据);

  //写

  wirte table . write(data, utf8 );

  })

  wirte table . on( open ,()={

  Console.log(开始写入数据)

  })

  //如果对stream.write(chunk)的调用返回false,则在适合继续向流中写入数据时,将触发“drain”事件。

  //即生产数据的速度快于写入速度。缓冲区填满后,将暂停生产以从底层读取数据。

  //释放可写缓冲区后,将发送一个drain事件,让生成器继续读取。

  wirte table . on( drain ,()={

  Console.log(继续写)

  })

  //在调用stream.end()方法并且所有数据都刷新到底层系统后,会触发“finish”事件。

  wirte table . on( finish ,()={

  Console.log(“数据写入完成”)

  })

  readable.on(end ,()={

  //在读取数据时通知可写流。

  wirteable.end()

  })

  //当在可读流上调用stream.pipe()方法以将此可写流添加到其目标集时,将触发“pipe”事件。

  //readable.pipe(destWriteable)

  wirteable.on(管道,()={

  Console.log(“管道流创建”)

  })

  wirte table . on( error ,()={

  Console.log(数据写入错误)

  })更多关于node的信息,请访问:nodejs教程!那就是说Nodejs: stream模块中核心模块的细节了(看怎么用)。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: