preface

This article mainly sorts out the Node.js modules and related apis that I often use in my work, and does not sort out all the modules of Node.js.

The purpose of writing is also very simple. On the one hand to consolidate the knowledge learned, on the other hand, I hope to be helpful to the students who are learning Node.js. 💪 💪 💪

Node.js concepts and features

Node.js is a JavaScript runtime environment based on Chrome V8 engine. Node.js uses an event-driven, non-blocking I/O model, making it lightweight and efficient.

Console – Console

Console Print information

console.log('Log message');
console.warn('Warning Message');
console.debug('Debug Info');
console.error(new Error('Error message'));
console.log('Hello: %s, this is: %s'.'Node.js'.'developer'); // Hello: node. js, I'm: developerCopy the code

Statistics the number of label occurrences

console.count('key'); //key:1
console.count('key'); //key:2
console.count('key'); //key:3
Copy the code

Statistical running time

console.time('100-elements');
for (let i = 0; i < 100; i++) {}
console.timeLog('100-elements'.'Finish the first one'); //100-elements: 0.092msfor (let i = 0; i < 100; i++) {}
console.timeEnd('100-elements'); / / 100 - elements: 6.659 msCopy the code

Chalk module

const chalk = require('chalk');

console.log(chalk.blue('Hello Node.js! '));
console.log(chalk.red('Hello Node.js! '));
console.log(chalk.green('Hello Node.js! '));
Copy the code

Assert – assertions

The Assert module provides a simple set of tests to test invariants. Write unit tests primarily in conjunction with the Mocha testing framework.

API categories:

  • Strict schema API.
  • Loose mode API.

Use strict mode whenever possible. Otherwise, abstract equality comparisons can lead to unexpected results.

 const assert = require('assert');

 const obj1 = { a: 1 };
 const obj2 = { a: '1'} assert.deepEqual(obj1, obj2); // Same, not the result we wantCopy the code

Use strict mode

  • const assert = require(‘assert’).strict;
  • API with Strict mode (including Strict in name)

Unit tests should be as simple as possible and the structure of the method under test must be predictable. If the method under test does not meet the above requirements you may need to refactor the code. Although the Assert module provides a number of apis, the following three are commonly used.

  • assert(value,[,message])
  • assert.deepStrictEqual(actual, expected[, message])
  • assert.strictEqual(actual, expected[, message])

Assert can also be used in conjunction with the IS-Type-of module and in place of an if statement. If the assertion fails, an AssertionError of type is thrown.

 const assert = require('assert').strict;
 const is = require('is-type-of');

 function plus(num1,num2){
    assert(is.int(num1),'num1 must be an integer ');
    assert(is.int(num2),'num2 must be an integer '); . }Copy the code

The power to assert module

 const assert = require('power-assert');
 const arr = [1,2,3]

 describe('power-assert', () => {  
   it('should be equal', () => {    
     assert(arr[0] === 2);     
   });
 });
Copy the code

Path – the path

The PATH module provides utilities for working with file paths and directory paths. The default action for the PATH module varies depending on the operating system on which the Node.js application is running. 👉 click here 👈

Get file name

 path.basename('/foo/bar/baz/asdf/quux.html'); //quux.html
 path.basename('/foo/bar/baz/asdf/quux.html'.'.html'); //quux.html
Copy the code

Get the extension

 path.extname('/foo/bar/baz/asdf/quux.html'); //.html
Copy the code

Access to the directory

 path.dirname('/foo/bar/baz/asdf/quux.html'); //foo/bar/baz/asdf
Copy the code

Stitching path

 path.join('/foo'.'bar'.'baz/asdf'.'quux'.'.. '); // /foo/bar/baz/asdf
Copy the code

Parsing path

  path.parse('/foo/bar/baz/asdf/quux.html'); / / return / / {root:'/',
  // dir: '/foo/bar/baz/asdf',
  // base: 'quux.html',
  // ext: '.html',
  // name: 'quux'}
Copy the code

An absolute path

Path.resolve () is processed from right to left with a given sequence of paths, each subsequent path being prefixed until an absolute path is constructed. For example, given a sequence of path fragments: /foo, /bar, baz, a call to path.resolve(‘/foo’, ‘/bar’, ‘baz’) returns /bar/baz. If the absolute path has not been generated after processing all the given path fragments, the current working directory is added.

path.resolve(); // Return the absolute path of the current working directory path.resolve('wwwroot'.'static_files/png/'.'.. /gif/image.gif'); // Returns if the current working directory is /home/myself-/ node'/home/myself/node/wwwroot/static_files/gif/image.gif'
Copy the code

Check whether it is an absolute path

 path.isAbsolute('/foo/bar'); //true
 path.isAbsolute('qux/'); //false
Copy the code

Path segment

 'foo/bar/baz'.split(path.sep); / / /'foo'.'bar'.'baz']
Copy the code

Fs – File system

Fs All file system operations are synchronous and asynchronous.

The asynchronous form always takes the completion callback as its last argument. The parameters passed to complete the callback depend on the method, but the first parameter is always reserved for exceptions. If the operation completes successfully, the first argument will be null or undefined.

Creating a folder

 const dir = path.join(__dirname,'/my'); // async fs.mkdir(dir, {recursive:true }, (err) => {
     if(err) throw err; }); / / synchronize the fs. MkdirSync (dir);Copy the code

Write files

 const file = path.join(__dirname,'/my/my.txt') // async fs.writefile (file,'Node.js'.'utf-8',(err)=>{
     if(err) throw err; }); / fs/synchronization. WriteFileSync (file,'Node.js'.'utf-8');

Copy the code

Read the file

/ / asynchronous fs. ReadFile (file,'utf-8',(err,data)=>{
     if(err) throw err; console.log(data); }) // synchronize fs.readfilesync (file,'utf-8')
Copy the code

Determine files/directories (recursively walking through folders can be useful)

 const file = path.join(__dirname,'/my/my.txt');
 const dir = path.join(__dirname,'/my/');

 const stat_file = fs.statSync(file);
 const stat_dir = fs.statSync(dir);
 stat_file.isFile(); //true
 stat_dir.isDirectory(); //true
Copy the code

Check whether a path exists

 fs.existsSync(file); //true
Copy the code

Read/write flow

 const file = path.join(__dirname,'/my/my.txt'); // write to const ws = fs.createWritestream (file,'utf8');
 ws.write('I'm a Node.js developer'); ws.end; Const rs = fs.createreadstream (file,'utf-8');
 rs.on('data',data=>{ console.log(data); // I'm a Node.js developer});Copy the code

extension

Recursively traverses all files in the specified folder

 const getFiles = (directory, file_list = []) => {
    const files = fs.readdirSync(directory);
    files.forEach(file => {
        var full_Path = path.join(directory, file);
        const stat = fs.statSync(full_Path);

        if (stat.isDirectory()) {
            getFiles(full_Path, file_list);
        } else{ file_list.push(full_Path); }});returnfile_list; } // call const files = getFiles('Folder directory');
Copy the code

Fs-extra module makes fs module function more perfect.

The Globby module helps you filter specific file types under folders, which is useful when traversing directories.

To learn more about the FS module API, please click here at 👉 👈

http – HTTP

The HTTP module encapsulates an HTTP server and HTTP client.

Creating an HTTP Server

 const http = require('http');

 const server = http.createServer((request, response) => {
     response.writeHead(200, { 'Content-Type': 'text/plain' });
     response.write('Hello World');
     response.end();
 });

 server.listen(3000, () => {
     console.log('server is listening on 3000... ');
 });
Copy the code

Create an HTTP client

 const http = require('http');
 
 const req = http.request({hostname: 'localhost',port: 3000}, res => {console.log(' status code:${res.statusCode}`); // Status code 200 res.on('data', data => {console.log(' received cancel:${data}`); // Receive message Hello World}); }); req.on('error', err => { console.log(err.message); }); req.end(); // End () must be calledCopy the code

️ when using http.request(), req.end() must always be called to indicate the end of the request, even if no data is written to the request body.

The Koa/Express framework can help you quickly create an HTTP server. 💻

Process – process

The Process object is a global variable that provides information about and controls the current Node.js process.

Get working directory

 process.cwd(); 
Copy the code

Withdraw from the process

 process.on('exit',code=>{ console.log(code); / / 100}); process.exit(100);Copy the code

View the memory usage of a process

process.memoryUsage(); // return //{// RSS: 19980288, // heapTotal: 6537216, //V8 memory total size // heapUsed: 4005104, //V8 memory used size // external: 8272 v8-managed memory usage of C++ objects bound to javascriptCopy the code

Node.js is a javascript runtime based on the V8 engine, which has around 1.4GB of memory available on 64-bit operating systems and around 0.7GB available on 32-bit operating systems.

Gets the command line arguments passed in

console.log(process.argv); // Start nodeindex.js arg1=1 arg2=2Copy the code

process.nextTick()

The process.nexttick () method adds the callback to the end of the current stack and executes it immediately after the current stack completes execution.

 console.log('开始');
 process.nextTick(() => {
   console.log('Callback at the next point in time');
 });
 console.log('schedule'); //output: // start // schedule // callback at the next point in timeCopy the code

Commonly used attributes

Process. pid // Returns the pid process.env of the process // Returns the containing user environment objectCopy the code

Standard flow object

  1. Process. stdin Standard input stream
  2. Process. stdout Standard output stream
  3. Process. stderr Standard error flow

Console.log () is implemented by process.stdout. Console.error () is implemented by process.srderr.

Use the cross-env module to set environment variables.

Child_process – Child process

The child_process module is mainly used to create child processes. The methods provided include synchronous and asynchronous versions. The methods mainly include the following (mostly asynchronous versions):

  • child_process.spawn(command[, args][, options])
  • child_process.execFile(file[, args][, options][, callback])
  • childProcess.exec(command[, options][, callback])
  • childProcess.fork(modulePath[, args][, options])

1. Fork () is a derivative of spawn() and is used to run the specified module. The most important feature of the parent-child process is its own IPC communication mechanism. 2. The main difference between exec() and execFile() is that exec() generates shells while execFile() does not, so execFile() is more efficient. Since a terminal is required to start the.bat and.cmd files on Windows, only exec() or spawn() with shell options can be used to run the.bat or.cmd files.

child_process.spawn()

 const { spawn } = require('child_process');
 const sp = spawn('node'['-v']);

 sp.stdout.on('data',data=>{
   console.log(data.toString());
 });

 sp.stderr.on('data', err => { console.error(err); / / v10.16.3}); sp.on('close', (code) => {
   console.log(`Code:${code}`); //Code:0 });Copy the code

child_process.exec()

  //child.js
  console.log('i am child');
  console.error('error');
  
  //parent.js
  const { exec } = require('child_process');
  const sp = exec('node ./client.js');

  sp.stdout.on('data',data=>{console.log(' child process output:${data.toString()}`); // child output: I am child}); sp.stderr.on('data', err => {console.error(' child process reported an error:${err}`); // Child process error :error}); sp.on('close', (code) => {
    console.log(`Code:${code}`); //Code:0 });Copy the code

child_process.fork()

  //parent.js
  const { fork } = require('child_process');

  const f = fork('./child.js');

  f.on('message',msg=>{
    console.log(`child message: ${msg}`); //child message: I am child }); // Send message f.end ('I am parent! ');
  
  //child.js
  process.on('message', msg=> {
    console.log('parent message:', msg); //parent message: I am parent! process.exit(); }); // Send a message to the parent process.send('I am child');
Copy the code

Process.send () is a synchronous method, so frequent calls can also cause thread blocking.

The main challenge for Node in CPU-intensive applications is that, due to single-threaded Javascript, long running computations (such as large loops) will result in CPU time slices that cannot be freed and subsequent I/ OS that cannot be initiated. However, if large computing tasks are properly adjusted and decomposed into several small tasks, the operations can be released timely without blocking the initiation of I/O calls. In this way, the benefits of parallel asynchronous I/O can be enjoyed and the CPU can be fully utilized.

extension

Resolve thread blocking caused by intensive computation with child_process.fork()

 //child.js
 process.on('message', msg => {
   if(msg === 'start') {for(leti = 0; i < 10000; i++){for(letj = 0; j<100000; j++){} } process.send('Complete');//运行完成
     process.exit();
   }
});

 //parent.js
 const { fork } = require('child_process');

 const f = fork('./client.js');

 f.on('message', msg => { console.log(msg); //Complete }); // Send the start message f.end ('start');
Copy the code

Cluster – cluster

Since node.js instances run on a single thread, the Cluster module starts multiple worker processes by child_process.fork() to handle the load in order to make full use of server resources.

The following code shows how to start multiple worker threads based on the number of operating system cores. After 3s, all worker threads will be terminated, and finally the worker thread will restart

 const cluster = require('cluster');
 const http = require('http'); Const numCPUs = require('os').cpus().length;

 if(cluster.ismaster) {console.log(' main process${process.pid}Running '); // Start the working process.for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
     }

     for (const id inCluster.workers) {// A work process exits cluster.workers[id].'exit', (code, signal) => {
            if(signal) {console.log(' The worker process has been signaled${signal}Kill `); }else if(code ! == 0) {console.log(' Worker process exits, exit code:${code}`);
            } else {
                console.log('Working process exits successfully'); }}); } cluster.on('exit', (worker, code, signal) => {console.log(' worker process${worker.process.pid}Closed (${signal || code}). Restarting... `); // Restart cluster.fork(); }); }else {
    http.createServer((req, res) => {
        res.writeHead(200);
        res.end('hello node.js'); }).listen(3000); Console. log(' worker process${process.pid}Has launched `); } // end all working processes after 3ssetTimeout(() => {
    for (const id incluster.workers) { cluster.workers[id].kill(); }}, 3000);Copy the code

How cluster works: When a cluster starts, it starts the TCP server internally and sends the TCP server socket file descriptor to the worker process when cluster.fork() starts the child process. If the process is replicated from cluster.fork(), NODE_UNIQUE_ID will be in its environment variable. If the worker process has a call to the listen() network port, it will get the file descriptor. Multiple subprocesses share ports through port reuse with SO_REUSEADDR(which allows multiple instances of the same server to be started on the same port).

The core of egg-Cluster module that provides multi-process capability for enterprise framework Egg is cluster module.

Buffer – Buffer

A Buffer is an array-like object that is used to manipulate bytes. The memory occupied by Buffer is not allocated by V8 and is off-heap memory.

Turn a string Buffer

 const str = 'hello Node.js.'
 Buffer.from(str,'utf8')
Copy the code

Turn the string Buffer

 const str = 'hello Node.js.'
 const buf = Buffer.from(str,'utf8');

 console.log(buf.toString('utf8')); // hello Node.js.Copy the code

Buffer stitching

 const str1 = 'hello Node.js.'
 const str2 = 'I am development'; 

 const buf1 = Buffer.from(str1,'utf8');
 const buf2 = Buffer.from(str2,'utf8');

 const length = buf1.length + buf2.length;
 const newBuffer = Buffer.concat([buf1,buf2],length);
 console.log(newBuffer.toString('utf8')); //hello Node.js.I am development
Copy the code

Buffer to copy

 const buf = Buffer.from('hello'.'utf8');
 const buf2 = Buffer.alloc(5);
 buf.copy(buf2);
 console.log(buf2.toString('utf8')); //helloCopy the code

Buffer to fill

 const buf = Buffer.alloc(10);
 buf.fill('A');
 console.log(buf.toString('utf8')); //AAAAAAAAAACopy the code

Check whether it is Buffer

const buf = Buffer.alloc(10); const obj = {}; console.log(Buffer.isBuffer(buf)); //trueconsole.log(Buffer.isBuffer(obj)); //false
Copy the code

The string is converted to hexadecimal

 const buf = Buffer.from('Hello Node.js '.'utf-8');
 console.log(buf.toString('hex')); //48656c6c6f204e6f64652e6a7320Copy the code

Hexadecimal conversion character string

 const hex = '48656c6c6f204e6f64652e6a7320';
 const buf= Buffer.from(hex,'hex');
 console.log(buf.toString('utf8')); //Hello Node.jsCopy the code

Querystring – querystring

The QueryString module is mainly used to parse and format URL query strings.

Query string to object

 const querystring = require('querystring');

 const obj = querystring.parse('foo=bar&abc=xyz&abc=123'); console.log(obj); //{ foo:'bar', abc: [ 'xyz'.'123']}Copy the code

Object to a query string

 const obj = { foo: 'bar', abc: [ 'xyz'.'123' ] };
 console.log(querystring.stringify(obj));//foo=bar&abc=xyz&abc=123
Copy the code

Query string percentage encoding

 const str = querystring.escape('foo=bar&abc=xyz&abc=123'); console.log(str); //foo%3Dbar%26abc%3Dxyz%26abc%3D123Copy the code

URL percentile encoding character decoding

 const str = querystring.unescape('foo%3Dbar%26abc%3Dxyz%26abc%3D123'); console.log(str); //foo=bar&abc=xyz&abc=123Copy the code

Module (module)

In the Node.js module system, each file is treated as an independent module. Node.js modules are divided into two types: one is the module provided by Node, called core module; The other is user-written modules called file modules.

The introduction of the module

 const fs = require('fs'); // load system module const myModule = require('./my.js'); Const myModule = require(const myModule = require('.. /test/my.js'); // Load the parenttest/ / my.js const myModule = require('/user/test/my.js'); / / load/user /test/ under the my.js moduleCopy the code

Introducing a module requires three steps:

  1. Path analysis
  2. File location
  3. Compile implementation

The core modules are compiled into binary executables during the compilation of Node source code. Some core modules are loaded directly into memory when the Node process starts, so file location and compile execution can be omitted when these core modules are introduced.

Module loading process

  1. Preferentially load from cache
  2. Path analysis
  3. File location
  4. Modules compiled

Loop in module

When the loop calls require(), a module may be returned with incomplete execution.

a.js

 console.log('a beginning');
 exports.done = false;
 const b = require('./b.js');
 console.log('在 a 中,b.done = %j', b.done);
 exports.done = true;
 console.log(End of the 'a');
Copy the code

b.js

 console.log('b start');
 exports.done = false;
 const a = require('./a.js');
 console.log('in b, a. tone = %j', a.done);
 exports.done = true;
 console.log(End of the 'b');
Copy the code

main.js

 console.log('the main start');
 const a = require('./a.js');
 const b = require('./b.js');
 console.log('In main, a.tone =%j, b.tone =%j', a.done, b.done);
Copy the code

When main.js loads a.js, a.js loads b.js. At this point, B.js will try to load A.js. To prevent an infinite loop, an unfinished copy of the A. js exports object is returned to the B. js module. Then B. Js completes the load and provides the EXPORTS object to the A. js module.

Gets the name of the directory where the module resides

 console.log(__dirname);
Copy the code

Get the module’s full name

 console.log(__filename);
Copy the code

The module exports and exports

Exports export

exports.[property] = any; exports = any; // Do not exportCopy the code

The module exports export

 module.export = any;
Copy the code

Module. exports is the real exposed export, and exports is a variable bound by module.exports by default. If module.exports does not have any properties or methods (empty objects), all properties and methods collected by exports are assigned to module.exports. If Module. exports already has some methods or attributes, the information collected by exports is ignored.

Example:

b.js

Exports. PI = 3.14; module.exports = { name:'Node.js'
 }
Copy the code

main.js

 const b = require('./b.js'); console.log(b.PI); //undefined console.log(b.name); //Node.jsCopy the code

VM – A VM

The VM module provides a set of apis for compiling and running code in the V8 virtual machine context. The VM module is not a secure virtual machine. Do not use it to run untrusted code

An alternative to eval()

 const vm = require('vm');

 let x = 5;
 const context = vm.createContext({});
 const script = new vm.Script('x=6; value=5-2'); script.runInContext(context); const { value } = context; console.log(x); // 5 console.log(value); / / 3Copy the code

Events – Event triggers

Events module is the core module of Node.js to realize event-driven. Almost all commonly used modules inherit events module.

Event definition trigger

 const EventEmitter = require('events'); const myEmitter = new EventEmitter(); // Register events myEmitter. On ('action',()=>{
    console.log('Trigger event');
 });

 myEmitter.emit('action');
Copy the code

Note the order in which the event is triggered and registered. If the event is called before the event is registered, the event will not be triggered.

Passing parameters

 const EventEmitter = require('events'); const myEmitter = new EventEmitter(); // Register events myEmitter. On ('action',(msg)=>{
    console.log(`${msg}Node.js`); }); // myEmitter. Emit ('action'.'Hello');
Copy the code

The eventEmitter. Emit () method can pass any number of arguments to the event callback function

Only trigger once

 const EventEmitter = require('events');

 const myEmitter = new EventEmitter();
 letm = 0; // Register the event myEmitter. Once ('action', () => { console.log(++m); }); // myEmitter. Emit ('action'); // Print :1 myEmitter. Emit ('action'); / / not print at allCopy the code

Remove an event

 const EventEmitter = require("events");
 const myEmitter = new EventEmitter();

 function callback() {
     console.log('Event triggered');
 }

 myEmitter.on('action', callback);
 myEmitter.emit('action'); The console. The log (` listenser number:${myEmitter.listenerCount('action')}`);

 myEmitter.removeListener('action',callback);
 myEmitter.emit('action'); The console. The log (` listenser number:${myEmitter.listenerCount('action')}`);
Copy the code

Timer-timer

The Timer module exposes a global API for functions that are scheduled to be called at some future time.

SetTimeout () and setInterval() are consistent with the browsing APIS, and are used for single and multiple timed tasks, respectively.

Process. NextTick () and setTimeout (fn, 0)

 setTimeout(()=>{
    console.log('setTimeout'); },0); process.nextTick(()=>{ console.log('process.nextTick'); });Copy the code

Each time the process.nexttick () method is called, the callback function is simply queued up for execution on the nextTick. Timer using red-black tree operation time complexity is 0(LG (n)),nextTick() time complexity is 0(1). By contrast, process.nexttick () is more efficient.

Process. NextTick () and setImmediate ()

 setImmediate(() => {
     console.log('setImmediate'); }) process.nexttick (() => {console.log()'process.nextTick'); // always print first});Copy the code

The callback function in process.nexttick () executes with higher precedence than setImmediate(). Process.nexttick () is the idle observer, and setImmediate() is the check mediate. In each cycle check, the IDLE observer precedes the I/O observer, and the I/O observer precedes the Check observer.

【 Event loop details 👉 here 👈】

reference

<< simple node.js >>

Node. Js Chinese website