Commonly used built-in modules for Node.js

1. Built-in module path

1.1. Understanding the path module

The path module is used to process paths and files, providing many useful methods.

And we know that the paths on Mac OS, Linux and windows are different

  • The window will use  \or  \\ as the separator of the file path, of course, it is also supported at present  /;

  • / Used as a separator for file paths on Mac OS, Linux and Unix operating systems  ;

\ So what should we do if we develop an application on the window using it  as a separator, and deploy it to Linux?

  • There will be some problems with the display path;

  • So in order to shield the differences between them, we can use modules for path operations during development  path ;

1.2. Common APIs of path

Get information from path

  • dirname: Get the parent folder of the file;

  • basename: get the file name;

  • extname: get the file extension;

const path = require("path");

const myPath = '/Users/coderwhy/Desktop/Node/课堂/PPT/01_邂逅Node.pdf';

const dirname = path.dirname(myPath);
const basename = path.basename(myPath);
const extname = path.extname(myPath);

console.log(dirname); // /Users/coderwhy/Desktop/Node/课堂/PPT
console.log(basename); // 01_邂逅Node.pdf
console.log(extname); // .pdf

splicing of paths

  • If we want to splice multiple paths, but different operating systems may use different separators;

  • At this time we can use path.jointhe function;

console.log(path.join('/user', 'why', 'abc.txt'));

Concatenate files with a folder

  • If we want to splice a certain file and folder, we can use  path.resolve;

    • resolve/The function will judge whether there is or ../or in front of the path we spliced  ./;

    • If there is an absolute path, the corresponding splicing path will be returned;

    • If not, the path will be concatenated with the folder where the current execution file is located

path.resolve('abc.txt'); // /Users/coderwhy/Desktop/Node/TestCode/04_learn_node/06_常见的内置模块/02_文件路径/abc.txt
path.resolve('/abc.txt'); // /abc.txt
path.resolve('/User/why', 'abc.txt'); // /User/why/abc.txt
path.resolve('User/why', 'abc.txt'); // /Users/coderwhy/Desktop/Node/TestCode/04_learn_node/06_常见的内置模块/02_文件路径/User/why/abc.txt

resolve In fact, we will also use it in webpack:

const CracoLessPlugin = require('craco-less');
const path = require("path");

const resolve = dir => path.resolve(__dirname, dir);

module.exports = {
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            modifyVars: { '@primary-color': '#1DA57A' },
            javascriptEnabled: true,
          },
        },
      },
    }
  ],
  webpack: {
    alias: {
      "@": resolve("src"),
      "components": resolve("src/components")
    }
  }
}

2. Built-in module fs

1.1. Know the fs module

fs is the abbreviation of File System, which means the file system.

For any language or framework that serves the server side, it usually has its own file system:

  • Because the server needs to place various data, files, etc. in different places;

  • For example, most of the user data may be placed in the database (we will learn later);

  • For example, some configuration files or user resources (pictures, audio and video) exist in the form of files on the operating system;

Node also has its own file system operation module, which is fs:

  • With the help of the file system encapsulated by Node, we can directly operate files on any operating system (window, Mac OS, Linux);

  • This is one of the reasons why Node can develop servers, and why it can become a popular tool such as front-end automation scripts;

There are many APIs for the Node file system: https://nodejs.org/dist/latest-v14.x/docs/api/fs.html

  • It is impossible and unnecessary for us to learn one by one;

  • This should be used more as a manual for API query, which can be queried when it is used;

  • In the learning phase, we only need to learn the most commonly used ones;

But most of these APIs provide three modes of operation:

  • Method 1: Synchronously operate files: the code will be blocked and will not continue to execute;

  • Method 2: Asynchronous callback function to operate the file: the code will not be blocked, and the callback function needs to be passed in. When the result is obtained, the callback function will be executed;

  • Method 3: Asynchronous Promise operation file: the code will not be blocked, and a Promise will be returned by  fs.promises calling the method operation, which can be processed by then and catch;

Here we take the status of a file as an example:

  • Note: all need to import  fs modules;

Method 1: Synchronously operate files

// 1.方式一: 同步读取文件
const state = fs.readFileSync('../aaa.txt');
console.log(state);

console.log('后续代码执行');


//Hello World!
//后续代码执行

Method 2: Asynchronous callback function to operate files

fs.readFile(
  './aaa.txt',
  {
    encoding: 'utf8',
  },
  (err, state) => {
    if (err) {
      console.log(err);
      return;
    }
    console.log(state);
  }
);
console.log('后续代码执行');

//后续代码执行
//Hello World!

Method 3: Asynchronous Promise operation file

fs.promises
  .readFile('./aaa.txt', {
    encoding: 'utf-8',
  })
  .then((res) => {
    console.log('获取到结果:', res);
  })
  .catch((err) => {
    console.log('发生了错误:', err);
  });

1.2. File descriptors

What are file descriptors?

On common operating systems, for each process, the kernel maintains a table of currently open files and resources.

  • Every open file is assigned a simple numeric identifier called a file descriptor.

  • At the system level, all file system operations use these file descriptors to identify and track each specific file.

  • Windows systems use a different but conceptually similar mechanism for tracking resources.

  • To make life easier for users, Node.js abstracts away specific differences between operating systems and assigns a numeric file descriptor to all open files.

fs.open() method is used to allocate a new file descriptor. Once allocated, a file descriptor can be used to read data from, write data to, or request information about a file.

const fs = require('fs');

// 打开一个文件
fs.open('./bbb.txt', (err, fd) => {
  if (err) {
    console.log('打开文件错误:', err);
    return;
  }

  // 1.获取文件描述符
  console.log(fd);

  // 2.读取到文件的信息
  fs.fstat(fd, (err, stats) => {
    if (err) return;
    console.log(stats);
  });
  // 3.手动关闭文件
  fs.close(fd, (err) => {
    if (err) {
      console.log(err);
    }
  });
});

1.3. Reading and writing files

If we want to operate on the contents of the file, we can use the read and write of the file at this time:

  • fs.readFile(path, [options], callback): read the content of the file;

  • fs.writeFile(file, data,[options], callback): write content in the file;

File writes:

fs.writeFile('../foo.txt', content, {}, err => {
  console.log(err);
})

In the above code, you will find that there is a curly brace without any content filled in. This is the option parameter filled in when writing:

  • flag: the way to write.

  • encoding: character encoding;

Let's look at the flag first:

  • There are many values ​​of flag: https://nodejs.org/dist/latest-v14.x/docs/api/fs.html#fs_file_system_flags

    • w Open file for writing, default value;

    • w+Open the file for reading and writing, or create the file if it does not exist;

    • r+ Open the file for reading and writing, and throw an exception if it does not exist;

    • rOpen the file for reading, the default value when reading;

    • aOpen the file for writing, placing the stream at the end of the file. Create the file if it does not exist;

    • a+Open the file for reading and writing, placing the stream at the end of the file. Create the file if it does not exist

Let's look at the encoding again:

  • I wrote an article about character encoding on Jianshu before: https://www.jianshu.com/p/899e749be47c

  • At present, UTF-8 encoding is basically used;

file read:

  • If encoding is not filled in, the returned result is Buffer;

fs.readFile('./foo.txt', {encoding: 'utf-8'}, (err, data) => {
  console.log(data);
})

1.4. Folder operations

1.4.1 Create a new folder

Use fs.mkdir()or fs.mkdirSync()create a new folder:

const fs = require('fs');

const dirname = '../why';

if (!fs.existsSync(dirname)) {
  fs.mkdir(dirname, (err) => {
    console.log(err);
  })
}

1.4.1 Read a folder

The folder structure if shown

1. Read the content of the folder and get the string of the file in the folder Result: [ 'aaa', 'bbb', 'nba.txt' ]

fs.readdir('./why', (err, files) => {
  console.log(files)
})

2. Read the folder and get the information of the files in the folder   

// 2.读取文件夹, 获取到文件夹中文件的信息
fs.readdir('./why', { withFileTypes: true }, (err, files) => {
  console.log(files);
})

Result: 2-folder 1-file

[
  Dirent { name: 'aaa', [Symbol(type)]: 2 },
  Dirent { name: 'bbb', [Symbol(type)]: 2 },
  Dirent { name: 'nba.txt', [Symbol(type)]: 1 }
]

3. Get the content of the folder recursively 

// 读取文件夹
function readFolders(folder) {
  fs.readdir(folder, {withFileTypes: true} ,(err, files) => {
    files.forEach(file => {
      if (file.isDirectory()) {
        const newFolder = path.resolve(dirname, file.name);
        readFolders(newFolder);
      } else {
        console.log(file.name);
      }
    })
  })
}

readFolders(dirname);

1.4.3 File/folder renaming

const fs = require('fs');

// 1.对文件夹进行重命名
fs.rename('./why', './kobe', (err) => {
  console.log('重命名结果:', err);
});

// 2.对文件重命名
fs.rename('./ccc.txt', './ddd.txt', (err) => {
  console.log('重命名结果:', err);
});

3. Built-in module events

3.1. Basic use

The core APIs in Node are all driven by asynchronous events:

  • In this system, certain objects (Emitters) emit an event;

  • We can listen to this event (Listeners), and the callback function passed in, this callback function will be called when the event is listened to;

Sending events and listening to events are done through the EventEmitter class, and they all belong to the events object.

  • emitter.on(eventName, listener): Listening events can also be used addListener;

  • emitter.off(eventName, listener): Remove the event listener, you can also use it removeListener;

  • emitter.emit(eventName[, ...args]): Send an event, which can carry some parameters;

// events模块中的事件总线
const EventEmitter = require('events')

// 创建EventEmitter的实例
const emitter = new EventEmitter()

// 监听事件
//接收参数
function handleWhyFn(name, age, height) {
  console.log('监听why的事件', name, age, height);
}
emitter.on('why', handleWhyFn)

// 发射事件
setTimeout(() => {
  // 传递参数
  emitter.emit('why', "coderwhy", 18, 1.88)

  // 取消事件监听
  emitter.off('why', handleWhyFn)

  setTimeout(() => {
    emitter.emit('why')
  }, 1000)
}, 2000);

3.2. Common methods

An instance of EventEmitter has some properties that can record some information:

  • emitter.eventNames(): Returns  EventEmitter对象an array of currently registered event strings;

  • emitter.getMaxListeners(): Returns the current  EventEmitter对象maximum number of listeners, which can be setMaxListeners()modified, the default is 10;

  • emitter.listenerCount(事件名称): Return  EventEmitter对象the current event name and the number of listeners;

  • emitter.listeners(事件名称): Returns  EventEmitter对象an array of all listeners on the current event listener;

const EventEmitter = require('events');

const bus = new EventEmitter();

bus.on('click', () => {});
bus.on('click', () => {});

bus.on('click', () => {});
bus.on('input', () => {});

// 1.获取所有监听事件的名称  [ 'click', 'input' ]
console.log(bus.eventNames());  

// 2.获取监听最大的监听个数    10
console.log(bus.getMaxListeners());

// 3.获取某一个事件名称对应的监听器个数  3
console.log(bus.listenerCount('click'));

// 4.获取某一个事件名称对应的监听器函数(数组)   
// [ [Function], [Function], [Function] ]
console.log(bus.listeners('click'));

3.3. Supplements to the method

emitter.once(eventName, listener): event listen once

const EventEmitter = require('events');

const emitter = new EventEmitter();

emitter.once('click', (args) => {
  console.log("监听到事件", args);
})

setTimeout(() => {
  emitter.emit('click', 'coder');
  emitter.emit('click', 'coder');
}, 2000);

emitter.prependListener(): Add the listening event to the front ba

emitter.on('click', (args) => {
  console.log("a监听到事件", args);
})

// b监听事件会被放到前面
emitter.prependListener("click", (args) => {
  console.log("b监听到事件", args);
})

emitter.prependOnceListener(): Add the listening event to the front, but only listen once

emitter.prependOnceListener("click", (args) => {
  console.log("c监听到事件", args);
})

emitter.removeAllListeners([eventName]): remove all listeners

// 移除emitter上的所有事件监听
emitter.removeAllListeners();
// 移除emitter上的click事件监听
emitter.removeAllListeners("click");

Guess you like

Origin blog.csdn.net/m0_50789696/article/details/129785097