Home Web Front-end JS Tutorial How to use node to create a readable flow pattern

How to use node to create a readable flow pattern

Jun 04, 2018 am 09:51 AM
node

This time I will show you how to use node to create a readable flow pattern, and what are the precautions for using node to create a readable flow pattern. The following is a practical case, let's take a look.

The readable stream of node is based on the event

The flow mode of the readable stream. This flow mode will have a "switch", and every time the "switch" is turned on When the flow mode takes effect, if this "switch" is set to pause, then this readable stream will not

read the file until the "switch" is reset to flow.

Reading file process

The process of reading file content is mainly:

  1. Open the file. If the file is successfully opened, the open event will be triggered. If the opening fails, the error event and close event will be triggered to close the file.

  2. Start reading the contents of the file and listen to the data event. The data is in a flowing state. Reading can be paused by modifying the status of the switch.

  3. Every time the content is read, it is put into the cache and the data is published through the data event.

  4. After reading the contents of the file, close the file.

This series of actions are all based on events, and we all know that events in node are implemented in a publish-subscribe model.

Let’s take a look at how node uses readable streams to read the contents of files?

node readable stream parameters

First we create a readable stream through the fs module. The readable stream accepts two parameters:

  1. The first parameter is the file address to be read. Specify here which file you want to read.

  2. The second parameter is optional. This parameter is an object used to specify some specific parameters of the readable stream.

Let’s explain the following parameters one by one:

  • highWaterMark: Set the high water mark. This parameter is mainly used to read files. When, the readable stream will read the contents of the file into the cache, and here we need to create a buffer to cache the data, so this parameter is used to set the size of the buffer. If this parameter is not set, readable The default configuration of the stream is 64k.

  • flags: This parameter is mainly used to set the execution mode of the file. For example, our specific operations are suitable for reading files or writing files. If we are writing to a file, we use w. If you are reading a file, then this operator should be r.

The following table illustrates that different symbols represent different meanings:

SymbolMeaningr Reading the file, the file does not exist and an error is reported r Read and write, the file does not exist and an error is reportedrsRead the file synchronously and ignore the cachewWrite the file, create it if it does not exist, clear it if it existswxWrite the file exclusivelyw Read and write the file, create it if it does not exist, clear it if it existswx Similar to w, exclusive mode OpenaAppend writingaxSimilar to a, write exclusivelya Read and append writing, create if it does not existax The role is the same as a Similar, but opens the file exclusively
  • autoClose: This parameter is mainly used to control the closing of files. If an error occurs during the file reopening or other operations, the file needs to be closed. Then this parameter is the function to set whether the file is automatically closed.

  • encoding: Use buffer in node to read binary data for file operations. When these data are displayed, we will see a bunch of gibberish, so we need to specify a specific encoding format for this data. The data will then be encoded and converted so that the converted data is data we can understand.

  • starts: This parameter is mainly used to specify the position from which to start reading the contents of the file. The default is to start from zero.

  • ends: This parameter is mainly used to specify the specific length of data to be read from the file. It needs to be explained here that this parameter includes its own position, which is the so-called package front And after the package.

Let’s take a look at specific examples of readable streams:

let fs = require("fs");
let rs = fs.createReadStream("./a.js", {
  highWaterMark: 3,
  encoding: "utf8",
  autoClose: true,
  start: 0,
  end: 9
});
rs.on("open", () => {console.log("open");});
rs.on("close", () => {console.log("close");});
rs.on("data", data => {
  console.log(data);
  rs.pause();//暂停读取 此时流动模式为暂停模式
});
setInterval(() => {
  rs.resume();//重新设置为流动模式,开始读取数据
}, 1000);
rs.on("end", () => { console.log("end"); });
rs.on("error", err => { console.log(err); });
Copy after login

The first step of handwritten readable streams

We said above that the readable stream of node is based on the core module events of node, so we need to inherit the events module when implementing our own readable stream. The code is as follows:

let fs = require('fs');
let EventEmitter = require('events');
class ReadStream extends EventEmitter {
}
Copy after login

Inheriting the EventEmitter class, we can use various methods in the EventEmitter class, and also use the publish-subscribe model to process events.

Step 2: Process the parameters of the readable stream configuration

We mentioned above that you can configure this when creating a readable stream in node Specific parameters of stream configuration, such as

let rs = fs.createReadStream("./a.js", {
  highWaterMark: 3,
  encoding: "utf8",
  autoClose: true,
  start: 0,
  end: 9
});
Copy after login

So for these parameters, the readable stream class we implement ourselves also needs to process these parameters, so how should these parameters be processed?

constructor(path, options = {}) {
  super();
  this.path = path; //指定要读取的文件地址
  this.highWaterMark = options.highWaterMark || 64 * 1024;
  this.autoClose = options.autoClose || true; //是否自动关闭文件
  this.start = options.start || 0; //从文件哪个位置开始读取
  this.pos = this.start; // pos会随着读取的位置改变
  this.end = options.end || null; // null表示没传递
  this.encoding = options.encoding || null;// buffer编码
  this.flags = options.flags || 'r';
  this.flowing = null; // 模式开关
  this.buffer = Buffer.alloc(this.highWaterMark);// 根据设置创建一个buffer存储读出来的数
  this.open();
}
Copy after login

The usual configuration principle is based on the parameters configured by the user. If the user does not set this parameter, the default configuration will be used.

The third step to implement a readable stream: open the file

The principle here is to use the open method in the node module fs. First, let's review the use of the fs.open() method.

fs.open(filename,flags,[mode],callback);
//实例
fs.open('./1,txt','r',function(err,fd){});
Copy after login

Need to explain here, Callback functionThere are 2 parameters in callback:

  1. The first one is error, and all asynchronous callbacks in node will A parameter returned to describe the specific error message

  2. The second parameter is fd, which is the file descriptor used to identify the file, which is equivalent to The first parameter of the open function

Okay, now let’s take a look at how to implement the open method of our own readable stream:

open() {
  fs.open(this.path, this.flags, (err, fd) => { 
    //fd标识的就是当前this.path这个文件,从3开始(number类型)
    if (err) {
      if (this.autoClose) { // 如果需要自动关闭则去关闭文件
        this.destroy(); // 销毁(关闭文件,触发关闭事件)
      }
      this.emit('error', err); // 如果有错误触发error事件
      return;
    }
    this.fd = fd; // 保存文件描述符
    this.emit('open', this.fd); // 触发文件的打开的方法
  });
}
Copy after login

From the code We can see from the above:

fs.open function is an asynchronous function, which means that the callback is executed asynchronously. When the file is successfully opened, the fd attribute is also obtained asynchronously. This needs to be noted. .

Another important point is that if an error occurs when opening the file, it means that the file opening failed, then the file needs to be closed at this time.

The fourth step to implement readable streams: read the file content

We mentioned in detail above that the readable stream itself defines a " switch", when we want to read the content in the file, we need to turn on this "switch", so how does the node readable stream itself turn on this "switch"?

Listen to data events

The node readable stream realizes the opening of this "switch" by listening to the data event:

rs.on("data", data => {
  console.log(data);
});
Copy after login

When the user listens to the data event When , the "switch" is turned on and the content is continuously read from the file. So how does node listen to data events?
The answer is the newListener of the event module

This is because the node readable stream is based on events, and in the event, the server can listen to all events from the user through the newListener event. Each Events have corresponding types. When the user listens to the data event, we can obtain it and then read the content in the file. So how can we implement our own readable stream?

// 监听newListener事件,看是否监听了data事件,如果监听了data事件的话,就开始启动流动模式,读取文件中的内容
this.on("newListener", type => {
  if (type === "data") {
    // 开启流动模式,开始读取文件中的内容
    this.flowing = true;
    this.read();
  }
});
Copy after login

好了,知道了这个"开关"是如何打开的,那么这个时候就到了真正读取文件中内容的关键时候了,先上代码先:

read() {
  // 第一次读取文件的话,有可能文件是还没有打开的,此时this.fd可能还没有值
  if (typeof this.fd !== "number") {
    // 如果此时文件还是没有打开的话,就触发一次open事件,这样文件就真的打开了,然后再读取
    return this.once("open", () => this.read());
  }
  // 具体每次读取多少个字符,需要进行计算,因为最后一次读取倒的可能比highWaterMark小
  let howMuchRead = this.end ? Math.min(this.end - this.pos + 1, this.highWaterMark) : this.highWaterMark;
  fs.read(this.fd, this.buffer, 0, howMuchRead, this.pos, (err, byteRead) => {
    // this.pos 是每次读取文件读取的位置,是一个偏移量,每次读取会发生变化
    this.pos += byteRead;
    // 将读取到的内容转换成字符串串,然后通过data事件,将内容发布出去
    let srr = this.encoding ? this.buffer.slice(0, byteRead).toString(this.encoding) : this.buffer.slice(0, byteRead);
    // 将内容通过data事件发布出去
    this.emit("data", srr);
    // 当读取到到内容长度和设置的highWaterMark一致的话,并且还是流动模式的话,就继续读取
    if ((byteRead === this.highWaterMark) && this.flowing) {
      return this.read();
    }
    // 没有更多的内容了,此时表示文件中的内容已经读取完毕
    if (byteRead < this.highWaterMark) {
      // 读取完成,发布end方法,并关闭文件
      this.emit("end");
      this.destory();
    }
  });
}
Copy after login

这里我们特别要注意的是:

  1. 文件是否已经打开,是否获取到fd,如果没有打开的话,则再次触发open方法

  2. 分批次读取文件内容,每次读取的内容是变化的,所以位置和偏移量是要动态计算的

  3. 控制读取停止的条件。

实现可读流第五步:关闭文件

好了,到现在,基础的读取工作已经完成,那么就需要将文件关闭了,上面的open和read方法里面都调用了一个方法:destory,没错,这个就是关闭文件的方法,好了,那么我们来看看这个方法该如何实现吧

destory() {
  if (typeof this.fd !== "number") {
    // 发布close事件
    return this.emit("close");
  }
  // 将文件关闭,发布close事件
  fs.close(this.fd, () => {
    this.emit("close");
  });
}
Copy after login

当然这块的原理就是调用fs模块的close方法啦。

实现可读流第六步:暂停和恢复

既然都说了,node可读流有一个神奇的"开关",就像大坝的阀门一样,可以控制水的流动,同样也可以控制水的暂停啦。当然在node可读流中的暂停是停止对文件的读取,恢复就是将开关打开,继续读取文件内容,那么这两个分别对应的方法就是pause()和resume()方法。

那么我们自己的可读流类里面该如何实现这两个方法的功能呢?非常简单:

我们在定义类的私有属性的时候,定义了这样一个属性flowing,当它的值为true时表示开关打开,反之关闭。

pause() {
  this.flowing = false;// 将流动模式设置成暂停模式,不会读取文件
}
resume() {
  this.flowing = true;//将模式设置成流动模式,可以读取文件
  this.read();// 重新开始读取文件
}
Copy after login

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎样利用JS做出引用传递与值传递

使用JS实做出加密解密操作

The above is the detailed content of How to use node to create a readable flow pattern. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
Two Point Museum: All Exhibits And Where To Find Them
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to delete node in nvm How to delete node in nvm Dec 29, 2022 am 10:07 AM

How to delete node with nvm: 1. Download "nvm-setup.zip" and install it on the C drive; 2. Configure environment variables and check the version number through the "nvm -v" command; 3. Use the "nvm install" command Install node; 4. Delete the installed node through the "nvm uninstall" command.

How to use express to handle file upload in node project How to use express to handle file upload in node project Mar 28, 2023 pm 07:28 PM

How to handle file upload? The following article will introduce to you how to use express to handle file uploads in the node project. I hope it will be helpful to you!

How to do Docker mirroring of Node service? Detailed explanation of extreme optimization How to do Docker mirroring of Node service? Detailed explanation of extreme optimization Oct 19, 2022 pm 07:38 PM

During this period, I was developing a HTML dynamic service that is common to all categories of Tencent documents. In order to facilitate the generation and deployment of access to various categories, and to follow the trend of cloud migration, I considered using Docker to fix service content and manage product versions in a unified manner. . This article will share the optimization experience I accumulated in the process of serving Docker for your reference.

An in-depth analysis of Node's process management tool 'pm2” An in-depth analysis of Node's process management tool 'pm2” Apr 03, 2023 pm 06:02 PM

This article will share with you Node's process management tool "pm2", and talk about why pm2 is needed, how to install and use pm2, I hope it will be helpful to everyone!

Pi Node Teaching: What is a Pi Node? How to install and set up Pi Node? Pi Node Teaching: What is a Pi Node? How to install and set up Pi Node? Mar 05, 2025 pm 05:57 PM

Detailed explanation and installation guide for PiNetwork nodes This article will introduce the PiNetwork ecosystem in detail - Pi nodes, a key role in the PiNetwork ecosystem, and provide complete steps for installation and configuration. After the launch of the PiNetwork blockchain test network, Pi nodes have become an important part of many pioneers actively participating in the testing, preparing for the upcoming main network release. If you don’t know PiNetwork yet, please refer to what is Picoin? What is the price for listing? Pi usage, mining and security analysis. What is PiNetwork? The PiNetwork project started in 2019 and owns its exclusive cryptocurrency Pi Coin. The project aims to create a one that everyone can participate

Let's talk about how to use pkg to package Node.js projects into executable files. Let's talk about how to use pkg to package Node.js projects into executable files. Dec 02, 2022 pm 09:06 PM

How to package nodejs executable file with pkg? The following article will introduce to you how to use pkg to package a Node project into an executable file. I hope it will be helpful to you!

Token-based authentication with Angular and Node Token-based authentication with Angular and Node Sep 01, 2023 pm 02:01 PM

Authentication is one of the most important parts of any web application. This tutorial discusses token-based authentication systems and how they differ from traditional login systems. By the end of this tutorial, you will see a fully working demo written in Angular and Node.js. Traditional Authentication Systems Before moving on to token-based authentication systems, let’s take a look at traditional authentication systems. The user provides their username and password in the login form and clicks Login. After making the request, authenticate the user on the backend by querying the database. If the request is valid, a session is created using the user information obtained from the database, and the session information is returned in the response header so that the session ID is stored in the browser. Provides access to applications subject to

What is a single sign-on system? How to implement it using nodejs? What is a single sign-on system? How to implement it using nodejs? Feb 24, 2023 pm 07:33 PM

What is a single sign-on system? How to implement it using nodejs? The following article will introduce to you how to use node to implement a single sign-on system. I hope it will be helpful to you!

See all articles