[Nodejs] nodejs built-in module (medium)

insert image description here

1. Road King processing module path


1.1 Module overview

In nodejs, path is a module that is frequently used, but people love and hate it. Partly because the documentation is not clear enough, partly because of the platform differences of the interface. Classify the interface of path according to its purpose, and after careful consideration, it will not be so confusing.

1.2 Get path/filename/extension

  • Get the path: path.dirname(filepath)
  • Get the file name: path.basename(filepath)
  • Get the extension: path.extname(filepath)

(1) Obtain the path where it is located.
Examples are as follows:

var path = require('path');
var filepath = '/tmp/demo/js/test.js';

// 输出:/tmp/demo/js
console.log( path.dirname(filepath) );

(2) Obtaining the file name
Strictly speaking, path.basename(filepath) is only the last part of the output path, and does not determine whether it is a file name. But most of the time, we can use it as a simple "get filename" method.

var path = require('path');

// 输出:test.js
console.log( path.basename('/tmp/demo/js/test.js') );

// 输出:test
console.log( path.basename('/tmp/demo/js/test/') );

// 输出:test
console.log( path.basename('/tmp/demo/js/test') );

What if you only want to get the file name, but not the file extension? You can use the second parameter.

// 输出:test
console.log( path.basename('/tmp/demo/js/test.js', '.js') );

(3) Get the file extension.
A simple example is as follows:

var path = require('path');
var filepath = '/tmp/demo/js/test.js';

// 输出:.js
console.log( path.extname(filepath) );

A more detailed rule is as follows: (assuming path.basename(filepath) === B )

  • Intercept from the last . of B until the last character.
  • If . does not exist in B, or the first character of B is ., then return an empty string.

Look directly at the example of the official document

path.extname('index.html')
// returns '.html'

path.extname('index.coffee.md')
// returns '.md'

path.extname('index.')
// returns '.'

path.extname('index')
// returns ''

path.extname('.index')
// returns ''

1.3 Path combination

path.join([...paths])
path.resolve([...paths])

(1) absolute path generated by path.resolve()
Syntax format:

path.resolve([...myPaths])

explain:

  • Resolves a sequence of paths or path fragments as absolute paths.
  • The returned path is processed from right to left, and each subsequent myPath is parsed in turn until a complete absolute path is constructed.

你可以想象现在你在shell下面,从左到右运行一遍cd path命令,最终获取的绝对路径/文件名,就是这个接口所返回的结果了。
Code example:

const path = require('path');

let arr1 = ['/foo1/foo2', 'dselegent', 'foo3'];
let result1 = path.resolve(...arr1);
console.log(result1); // 打印结果:/foo1/foo2/dselegent/foo3

let arr2 = ['/foo1/foo2', '/dselegent', 'foo3'];
let result2 = path.resolve(...arr2);
console.log(result2); // 打印结果:/dselegent/foo3
const path = require('path');

// 假设当前工作路径是 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path
console.log( path.resolve('') )

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path
console.log( path.resolve('.') )

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz') );

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz/') );

// 输出 /tmp/file
console.log( path.resolve('/foo/bar', '/tmp/file/') );

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path/www/js/mod.js
console.log( path.resolve('www', 'js/upload', '../mod.js') );

(2) path.join() joins multiple paths
If we manually join the paths, it is easy to make mistakes. At this time, you can use the path.join() method to join the paths.

Grammar format:

path.join([...paths]);

Explanation: Concatenates all the given path fragments together using the platform-specific delimiter as a delimiter, then normalizes the resulting path.

Code example:

const path = require('path');

const result1 = path.join(__dirname, './app.js');
console.log(result1); // 返回:/Users/smyhvae/dselegent/app.js

const result2 = path.join('/foo1', 'foo2', './foo3');
console.log(result2); // 返回:/foo1/foo2/foo3

const result3 = path.join('/foo1', 'foo2', '/foo3');
console.log(result3); // 返回:/foo1/foo2/foo3

(3) The difference path.resolvefrompath.join
path.resolve and path.joinare both methods under the path core module, used to splice paths.

can be concatenated into a complete path.

const path = require("path");

var dirname = '/User/Desktop';
var basename = 'abc.txt';

path.join(dirname, basename);  // /User/Desktop/abc.txt

path.resolve(dirname, basename);  // /User/Desktop/abc.txt

If dirname starts with ./, .../, without /, then resolve will find the root directory under the disk

const path = require("path");
 
var dirname = '../User/Desktop';
var basename = 'abc.txt';
 
path.join(dirname, basename);  // ../User/Desktop/abc.txt
 
path.resolve(dirname, basename);  // /Users/Desktop/node/User/Desktop/abc.txt

If basename starts with /, then resolve will directly return basename

const path = require("path");
 
var dirname = '/User/Desktop';
var basename = '/abc.txt';
 
path.join(dirname, basename);  // /User/Desktop/abc.txt
 
path.resolve(dirname, basename);  // /abc.txt

1.4 Several common paths

__dirname: This is a constant, which means: the complete directory where the current execution file is located.
__filename: This is a constant. Indicates: the complete directory + file name of the currently executed file.
process.cwd: Get the directory name when the Node command is currently executed.
Code example:

console.log(__dirname);
console.log(__filename);
console.log(process.cwd());

operation result:

$ node app.js

/Users/smyhvae/dselegent
/Users/smyhvae/dselegent/app.js
/Users/smyhvae/dselegent

2. Local file operation module fs


The difference between synchronous and asynchronous in Node.js
The fs module has two forms of synchronous and asynchronous for almost all operations on files. For example: readFile()and readFileSync().

the difference:

  • Synchronous calls block the execution of code, asynchronous calls do not.
  • The asynchronous call will send the reading task to the task queue, and will not call back until the task execution is completed.
  • Exception handling: Synchronization must use the try catch method, asynchrony can pass the first parameter of the callback function. ★★★★★

2.1 File reading

synchronous read

var fs = require('fs');
var data;

try{
    
    
    data = fs.readFileSync('./fileForRead.txt', 'utf8');
    console.log('文件内容: ' + data);
}catch(err){
    
    
    console.error('读取文件出错: ' + err.message);
}

The output is as follows:

/usr/local/bin/node readFileSync.js
文件内容: hello world

asynchronous read

var fs = require('fs');

fs.readFile('./fileForRead.txt', 'utf8', function(err, data){
    
    
    if(err){
    
    
        return console.error('读取文件出错: ' + err.message);
    }
    console.log('文件内容: ' + data);
});

The output is as follows

/usr/local/bin/node readFile.js
文件内容: hello world

fs/promises 从 Node.js 14 开始可用 从 Node.js 14 开始,fs 模块提供了两种使用基于 promises 的文件系统的方法。这些 promises 可以通过 require('fs').promises 或 require('fs/promises') 获得。

import {
    
     readFile } from 'fs/promises';

try {
    
    
  const contents = await readFile(filePath, {
    
     encoding: 'utf8' });
  console.log(contents);
} catch (err) {
    
    
  console.error(err.message);
}

2.2 File writing

Remarks: The following code, if the file does not exist, creates the file; if the file exists, overwrites the file content;

write asynchronously

var fs = require('fs');

fs.writeFile('./fileForWrite.txt', 'hello world', 'utf8', function(err){
    
    
    if(err) throw err;
    console.log('文件写入成功');
});

write synchronously

var fs = require('fs');

try{
    
    
    fs.writeFileSync('./fileForWrite1.txt', 'hello world', 'utf8');
    console.log('文件写入成功');
}catch(err){
    
    
    throw err;
}

promises

import {
    
     writeFile } from 'fs/promises';

try {
    
    
  const contents = await writeFile('message.txt', 'hello world', {
    
     encoding: 'utf8' });
  console.log(contents);
} catch (err) {
    
    
  // When a request is aborted - err is an AbortError
  console.error(err);
}

2.3 Whether the file exists

fs.exists()It is already in deprecatedthe state, and now you can judge whether the file exists through the following code.

asynchronous version

const fs = require('fs')

//检查文件是否存在于当前目录中
fs.access('package.json', fs.constants.F_OK, err => {
    
    
    if(err) {
    
    
        console.log('package.json不存在于当前目录中')
        return
    }
    console.log('package.json存在于当前目录中')
})

fs.access('index.js', fs.constants.F_OK, err => {
    
    
    if(err) {
    
    
        console.log('index.js不存在于当前目录中')
        return
    }
    console.log('index.js存在于当前目录中')
})

fs.access()In addition to judging whether the file exists (default mode), it can also be used to judge the permissions of the file.

Remarks: fs.constants.F_OKconstants cannot be obtained (node ​​v6.1, under mac 10.11.4, fs.constantsyes undefined)

Synchronize

import {
    
     accessSync, constants } from 'fs';

try {
    
    
  accessSync('etc/passwd', constants.R_OK );
  console.log('can read');
} catch (err) {
    
    
  console.error('no access!');
}

promises

import {
    
     access, constants } from 'node:fs/promises';

try {
    
    
  await access('/etc/passwd', constants.R_OK);
  console.log('can access');
} catch {
    
    
  console.error('cannot access');
}

2.4 Delete files

async version

var fs = require('fs');

fs.unlink('./fileForUnlink.txt', function(err){
    
    
    if(err) throw err;
    console.log('文件删除成功');
});

sync version

import {
    
     unlinkSync } from 'fs';

try {
    
    
  unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
    
    
  // handle the error
}

promises

import { unlink } from 'fs/promises';

try {
  await unlink('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}

2.5 Create directory

Asynchronous version (throws an error if the directory already exists)

// fs.mkdir(path[, mode], callback)
var fs = require('fs');

fs.mkdir('sub', function(err){
    
    
    if(err) throw err;
    console.log('创建目录成功');
});

sync version

// fs.mkdirSync(path[, mode])
var fs = require('fs');

try{
    
    
    fs.mkdirSync('hello');
    console.log('创建目录成功');
}catch(e){
    
    
    throw e;
}

promises

import {
    
     mkdir } from 'fs/promises';

try {
    
    
  const createDir = await mkdir(projectFolder, {
    
     recursive: true });
  console.log(`created ${
      
      createDir}`);
} catch (err) {
    
    
  console.error(err.message);
}

2.6 Traversing directories

Synchronous version, note: fs.readdirSync() will only read one layer, so it is necessary to determine whether the file type is a directory, and if so, perform recursive traversal.

// fs.readdirSync(path[, options])
var fs = require('fs');
var path = require('path');
var getFilesInDir = function(dir){
    
    
    var results = [ path.resolve(dir) ];
    var files = fs.readdirSync(dir, 'utf8');
    files.forEach(function(file){
    
    
        file = path.resolve(dir, file);
        var stats = fs.statSync(file);
        if(stats.isFile()){
    
    
            results.push(file);
        }else if(stats.isDirectory()){
    
    
            results = results.concat( getFilesInDir(file) );
        }
    });
    return results;
};
var files = getFilesInDir('../');
console.log(files);

2.7 Read directory

import {
    
     readdir } from 'fs/promises';

try {
    
    
  const files = await readdir(path);
  for (const file of files)
    console.log(file);
} catch (err) {
    
    
  console.error(err);
}

2.8 Delete directory

// 删除目录(前提没有文件在里面)
fs.rmdir('./avatar', err => {
    
    
  if (err && err.code === 'ENOENT') {
    
    
    console.log('目录不存在');
  }
});

2.9 Delete the entire directory

//1
const fs = require("fs")
fs.("./avatar",(err,data)=>{
    
    
    // console.log(data)
    data.forEach(item=>{
    
    
        fs.unlinkSync(`./avatar/${
      
      item}`)
    })

    fs.rmdir("./avatar",(err)=>{
    
    
        console.log(err)
    })
})

//2
const fs = require('fs')
fs.readdir("./avatar").then(async (data)=>{
    
    
    let arr = []
    data.forEach(item=>{
    
    
        arr.push(fs.unlink(`./avatar/${
      
      item}`))
    })
    await Promise.all(arr)
    fs.rmdir("./avatar")
})

//3
const fs = require('fs').promises;
fs.readdir('./image2').then(async data => {
    
    
  await Promise.all(data.map(item => fs.unlink(`./image2/${
      
      item}`)));
  await fs.rmdir('./image2');
});

2.10 File Renaming

async version

// fs.rename(oldPath, newPath, callback)
var fs = require('fs');

fs.rename('./hello', './world', function(err){
    
    
    if(err) throw err;
    console.log('重命名成功');
});

sync version

// fs.renameSync(oldPath, newPath)
var fs = require('fs');

fs.renameSync('./world', './hello');
promises

import {
    
     rename } from 'fs/promises';

try {
    
    
  await rename('./world', './hello');
  console.log(`rename`);
} catch (err) {
    
    
  console.error(err.message);
}

2.11 Get file status

(1) Asynchronous: fs.stat(path, callback): path is a string representing the path, and callback receives two parameters (err, stats), where stats is an instance of fs.stats;

(2) Synchronization: fs.statSync(path) only receives a path variable, and fs.statSync(path) is actually an instance of fs.stats;

method

  • stats.isFile() – whether it is a file
  • stats.isDirectory() – whether directory
// Node.js program to demonstrate the 
// fs.statSync() method 
  
// Import the filesystem module 
const fs = require('fs'); 
  
// Getting information for a file 
statsObj = fs.statSync("test_file.txt"); 
  
console.log(statsObj);  
console.log("Path is file:", statsObj.isFile()); 
console.log("Path is directory:", statsObj.isDirectory()); 
  
// Getting information for a directory 
statsObj = fs.statSync("test_directory"); 
  
console.log(statsObj); 
console.log("Path is file:", statsObj.isFile()); 
console.log("Path is directory:", statsObj.isDirectory());

output:

Stats {
    
    
  dev:3229478529,
  mode:33206,
  nlink:1,
  uid:0,
  gid:0,
  rdev:0,
  blksize:4096,
  ino:1970324837039946,
  size:0,
  blocks:0,
  atimeMs:1582306776282,
  mtimeMs:1582482953967,
  ctimeMs:1582482953968.2532,
  birthtimeMs:1582306776282.142,
  atime:2020-02-21T17:39:36.282Z,
  mtime:2020-02-23T18:35:53.967Z,
  ctime:2020-02-23T18:35:53.968Z,
  birthtime:2020-02-21T17:39:36.282Z
}
Path is file:true
Path is directory:false
Stats {
    
    
  dev:3229478529,
  mode:16822,
  nlink:1,
  uid:0,
  gid:0,
  rdev:0,
  blksize:4096,
  ino:562949953486669,
  size:0,
  blocks:0,
  atimeMs:1582482965037.8445,
  mtimeMs:1581074249467.7114,
  ctimeMs:1582482964979.8303,
  birthtimeMs:1582306776288.1958,
  atime:2020-02-23T18:36:05.038Z,
  mtime:2020-02-07T11:17:29.468Z,
  ctime:2020-02-23T18:36:04.980Z,
  birthtime:2020-02-21T17:39:36.288Z
}
Path is file:false
Path is directory:true

2.12 Append file content

fs.appendFile(file, data[, options], callback)

  • file: It can be a file path or a file handle. (Can it also be a buffer?)
  • data: the content to append. string or buffer.
  • options
    • encoding: encoding, the default is utf8
    • mode: default is 0o666
  • flag: the default is a

Note: If file is a file handle, then

  • The file needs to be open before starting to append data.
  • file needs to be closed manually.
var fs = require('fs');
fs.appendFile('./extra/fileForAppend.txt', 'hello', 'utf8', function(err){
    
    
    if(err) throw err;
    console.log('append成功');
});

3. Event mechanism module events


Node.js has multiple built-in events. We can bind and listen to events by introducing eventsmodules and instantiating classes, as shown in the following example:EventEmitter

// 引入 events 模块
var EventEmitter = require('events');
// 创建 eventEmitter 对象
var event = new EventEmitter();

The following program binds event handlers:

// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);

We can trigger events programmatically:

// 触发事件
eventEmitter.emit('eventName');

EventEmitterEach event of is composed of an event name and several parameters. The event name is a string, which usually expresses certain semantics. For each event, EventEmitterseveral event listeners are supported.

When an event is triggered, the event listeners registered to this event are called in turn, and the event parameters are passed as callback function parameters.

Let us explain this process with the following example:

// 引入 events 模块
var EventEmitter = require('events');
// 创建 eventEmitter 对象
var event = new EventEmitter();
event.on('someEvent', function(arg1, arg2) {
    
     
    console.log('listener1', arg1, arg2); 
}); 
event.on('someEvent', function(arg1, arg2) {
    
     
    console.log('listener2', arg1, arg2); 
}); 
event.emit('someEvent', 'arg1 参数', 'arg2 参数'); 

Execute the above code, the result of the operation is as follows:

$ node event.js 
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数

In the above example, two event listeners are registered eventfor the event , and then the event is triggered.someEventsomeEvent

In the running result, you can see that the two event listener callback functions are called successively. This is EventEmitterthe simplest usage.

EventEmitterSeveral properties are provided, such as onand emit. onFunctions are used to bind event functions, emitproperties are used to trigger an event

Guess you like

Origin blog.csdn.net/weixin_43094619/article/details/131910037