likes
comments
collection
share

文件可读流可写流、drain事件,背压机制

作者站长头像
站长
· 阅读数 23

可读流案例

// 文件可读流创建和消费
const fs = require("fs");
let rs = fs.createReadStream("test.txt", {
  flags: "r",
  encoding: null,
  fd: null,
  mode: 438,
  autoClose: true,
  start: 0,
  //   end:3,
  highWaterMark: 4,
});

// rs.on('data',(chunk)=>{
//     console.log(chunk.toString())
//     rs.pause() // 暂停
//     setTimeout(() => {
//         rs.resume() // 切回流动状态
//     }, 1000); // 1秒后继续,直到结束
// })

// rs.on("readable", () => {
//   //   let data = rs.read();
//   //   console.log(data);
//   let data;
//   //   while ((data = rs.read()) !== null) {
//   //     console.log(data.toString());
//   //   }
//   while ((data = rs.read(2)) !== null) { // 每次读两字节,缓冲区读完之后取highWaterMark字节长度到缓冲区
//     console.log(data.toString());
//     console.log(rs._readableState.length);
//   }
// });

rs.on("open", (fd) => {
  console.log(fd, "file open");
});

rs.on("close", (fd) => {
  console.log("默认不会被执行,数据被读取完(消费)后才会被执行");
});

rs.on("data", (chunk) => {
  console.log(chunk);
});

rs.on("end", () => {
  console.log('数据被清空过之后会被执行');
});

rs.on("err", (err) => {
  console.log('出错时会被执行');
});

可写流案例

const ws = fs.createWriteStream("test.txt", {
  flags: "w",
  mode: 438,
  fd: null,
  encoding: "utf-8",
  start: 0,
  highWaterMark: 3,
});

// ws.write("写入内容", () => {
//   console.log("write over1");
// });
// ws.write("可以多次写入,后面的默认会被追加", () => {
//   console.log("write over2");
// });

// ws.write(1, () => { // 会报错,这里默认接收字符串或者buffer => fs rs
//   console.log("write over1");
// });

ws.on("open", (fd) => {
  console.log("open", fd);
});

ws.on("close", () => {
  // 数据写入操作全部完成后再执行,end之后
  console.log("file close");
});

// end执行之后就意味着数据写入操作完成
ws.end(); // end中也可以放入要写的内容,最后最终执行写入

ws.on("err", (err) => {
  console.log("err");
});

可写流写入速度问题

let ws = fs.createWriteStream("test.txt", {
  highWaterMark: 3,
});

let flag = ws.write("1");
console.log(flag); // true

flag = ws.write("2");
console.log(flag);// true

flag = ws.write("3");
console.log(flag); // false ,
// 1,第一次调用write方法时是将数据直接写入到文件中
// 2,第二次开始write方法就是将数据写入至缓存区
// 3,生产速度和消费数据不一样,一般情况下生产速度要比消费速度快很多
// 4,当flag为false之后,false不代表当前数据不能被执行写入,但是我们应该告知数据生产者,当前消费速度已经跟不上生产速度,这时候我们会将
// 可读流的模块修改为暂停模式
// 5,当数据生产者暂停之后,消费者会慢慢消化它内部缓存中的数据,直到我们可再次被执行写入操作
// 6,当缓冲区可以继续写入数据时通过drain时间让生产者直到
ws.on("drain", () => {
  console.log("drain work");
});

控制写入速度,被压机制

分批限流

let ws = fs.createWriteStream("test.txt", {
  highWaterMark: 3,
});
// ws.write('前端性能')
let source = "前端性能".split("");
let num = 0;
let flag = true;
function excuteWrite() {
  flag = true;
  while (num !== 4 && flag) {
    flag = ws.write(source[num]);
    num++;
  }
}
excuteWrite();
ws.on("drain", () => {
  console.log("drain work");
  excuteWrite();
});

或者这里直接使用rs.pipe(ws)