Have an interview before, for front-end developers, it is necessary to know a background language.
At that time, I was asked such a few questions, although I did not write in the content of the article, you can go to study with these questions, to find the corresponding answer, is also a kind of promotion!
- What’s the difference between a browser event loop and a Node event loop?
commonjs
therequire
The implementation principle of?- The ES6
import
andcommonjs
What’s the difference between require of? - Writing a
EventEmmit
class
The following will be aimed at these problems, an article, welcome your attention.
Node
Why learn Nodejs
- Enterprise needs
- Experience in server-side development is a plus
- Full stack engineer
- Basic web development skills
- The service side
- The front end
- O&m deployment related work
What is the Node
Node.js is a JavaScript runtime environment based on Chrome’S V8 engine. Node.js uses an event-driven, non-blocking I/O model, making it lightweight and efficient.
Current stable version :14.15.1 Long Term Support (LTS
Install the node
Download from the official website => One-click installation, click and click to install.
Ps: If you have changed the installation path of the Windows computer, please modify the environment variables by yourself
Of course, the latest version of Node is 14.15.1, and you can download the latest version for installation now
The installation is successful.
The preparatory work
-
Run the node program
console.log('hello node'); console.log('run my use:node 01-runnode'); Copy the code
Run: node 01 – runnode. Js
Each js file modification takes effect only after you re-execute it. After nodemon is installed, you can monitor file changes and automatically restart the js file
npm i -g nodemon
Then run nodemon 01-runNode.js
-
Mode node program: debug-start Debugging
REPL(interactive interpreter)
- Expression operation
- Use the variable
- Multiline expression
- REPL command
- CTRL + C – Exit the terminal.
- Press CTRL + C twice – Exit Node REPL.
- CTRL + d – Exit Node REPL.
- Up/Down – View the history command entered
- TAB – Lists the current commands
- .help – Lists the commands used
- .break – Exits a multi-line expression
- . Clear – Exits a multi-line expression
- . Save filename – Saves the current Node REPL session to the specified file
- .load filename – Loads the contents of the file for the current Node REPL session.
The callback function
A direct example of Node.js asynchronous programming is callbacks.
Asynchronous programming relies on callbacks, but you can’t say that using callbacks makes the program asynchronous.
Callbacks are called when the task is complete. Node uses a large number of callbacks. All Node apis support callbacks.
For example, we can read a file while executing other commands, and when the file is read, we return the contents of the file as arguments to the callback function. This way there is no blocking or waiting for file I/O while the code executes. This greatly improves the performance of Node.js and can handle a large number of concurrent requests.
Block of code
// Blocking code
const fs = require('fs');
const data = fs.readFileSync('01-runnode.js');
console.log(data.toString());
Copy the code
Non-blocking code
const fs = require('fs');
fs.readFile('01-runnode.j'.function(err,data) {
if(err){
console.log(err.stack);
return;
}
console.log(data.toString());
});
console.log('Proceed');
Copy the code
The first instance executes the program after the file has been read. In the second instance, we don’t have to wait for the file to be read, so we can execute the following code while the file is read, greatly improving the performance of the program.
Therefore, blocking is done sequentially, and non-blocking is not, so if we need to handle the arguments to the callback function, we need to write them inside the callback function.
Event loop
Node.js is a single-process, single-threaded application, but it supports concurrency through events and callbacks, so it performs very well.
Each API of Node.js is asynchronous and runs as a separate thread, using asynchronous function calls, and handling concurrency.
Node.js implements basically all of its event mechanisms using the Observer pattern in the design pattern.
Node.js single-threading is similar to entering a while(true) event loop until no event observer exits. Each asynchronous event generates an event observer and calls the callback function if an event occurs.
Event driver
Node.js uses an event-driven model. When the Web server receives a request, it closes it and processes it before serving the next Web request.
When the request completes, it is put back on the processing queue, and when it reaches the beginning of the queue, the result is returned to the user.
This model is very efficient and very scalable because the WebServer is always accepting requests without waiting for any read or write operations. (This is also known as non-blocking IO or event-driven IO)
In the event-driven model, a main loop is generated to listen for events and the callback function is fired when an event is detected.
This is how the whole event-driven process is implemented, and it’s very neat. Somewhat similar to the Observer pattern, an event acts as a Subject, and all handlers registered with the event act as observers.
Node.js has several built-in events. We can bind and listen for events by introducing the Events module and instantiating EventEmitter class, as shown in the following example:
Create 03 – eventEmitter. Js
// Introduce the Event module
const events = require('events');
// Create an eventEmitter object
const eventEmitter = new events.EventEmitter();
// Create an event handler
const connectHandler = function connected() {
console.log('Connection successful');
// Triggers the data_Received event
eventEmitter.emit('data_received');
}
// Bind the Connection event handler
eventEmitter.on('connection', connectHandler);
// Bind the data_received event using an anonymous function
eventEmitter.on('data_received'.function() {
console.log('Data received successfully');
})
// Triggers the Connection event
eventEmitter.emit('connection');
console.log('Program completed');
Copy the code
Perform:
Connection successful Data received successful program execution completedCopy the code
Buffer
The JavaScript language itself has only string data types, not binary data types.
But when dealing with things like TCP streams or file streams, you must use binary data. Therefore, in Node.js, we define a Buffer class, which is used to create a Buffer dedicated to binary data.
In Node.js, the Buffer class is a core library shipped with the Node kernel. Buffer brings a way for Node.js to store raw data, allowing Node.js to process binary data, and it is possible to use Buffer whenever you need to process data moved in an I/O operation in Node.js. The raw data is stored in an instance of the Buffer class. A Buffer is similar to an array of integers, but it corresponds to a chunk of raw memory outside of the V8 heap memory.
// Buffer: an array of octets that can effectively store binary data in JS
/ / create
const buf1 = Buffer.alloc(10);
console.log(buf1);
// Create by data
const buf2 = Buffer.from('hello world');
console.log(buf2);
const buf3 = Buffer.from([1.2.3]);
console.log(buf3);
/ / write
buf1.write('hello buffer');
console.log(buf1);
/ / read
console.log(buf2.toString());
console.log(buf2.toString('base64'));
/ / merge
const buf4 = Buffer.concat([buf1,buf2]);
console.log(buf4.toString());
Copy the code
The Stream (flow)
The pipe flow
Pipes provide a mechanism for an output stream to an input stream. Usually we use it to get data from one stream and pass it to another.
As shown in the picture above, we compare a file to a bucket of water, and the water is the contents of the file. We connect the two buckets with a pipe to make the water flow from one bucket to the other, thus slowly realizing the copying process of large files.
In the following example, we read the contents of one file and write the contents to another file.
const fs = require('fs');
// Create a readable stream
const readerStream = fs.createReadStream('./package.json');
// Create a writable stream
const writerStream = fs.createWriteStream('./test.txt');
// Set encoding to UTf8
readerStream.pipe(writerStream);
console.log('Execution completed');
Copy the code
Chain flow
Chaining is a mechanism for creating chains of multiple stream operations by connecting output streams to another stream. Chain flows are generally used for pipe operations
The next step is to use pipes and chaining to compress and decompress files.
const fs = require('fs');
const zlib = require('zlib');
// Compress test.txt to test.zip
fs.createReadStream('./test.txt').pipe(zlib.createGzip()).pipe(fs.createWriteStream('test.zip'));
console.log('File compression successful');
Copy the code
Module system
To make node.js files callable to each other, Node.js provides a simple module system.
Modules are the basic building blocks of a Node.js application, and there is a one-to-one correspondence between files and modules. In other words, a node.js file is a module. This file may be JavaScript code, JSON, or a compiled C/C++ extension.
CommonJS module
In Node.js, creating a module is as simple as creating main.js
const Hello = require('./hello');
hello.world();
Copy the code
Node.js provides exports and require objects. Exports are the interfaces that a module exposes, and require is used to obtain the interface of a module from an external source, i.e. the exports object of the module
Next we create the hello.js file as follows:
exports.world = function() {
console.log('hello world');
}
Copy the code
Sometimes we just want to encapsulate an object into a module in the following format
module.exports = function() {
// ...
}
Copy the code
Such as:
function Hello() {
let name;
this.setName = function(myName) {
name = myName
}
this.sayHello = function() {
console.log('hello', name); }}module.exports = Hello;
Copy the code
So we can get the object directly:
const hello = new Hello();
hello.setName('Little Horse');
hello.sayHello();
Copy the code
Exports = Hello instead of exports.world = function(){}. When the module is referenced externally, its interface object is the Hello object itself, not the original exports.
Where is the server module
As you may have noticed, we already use modules in our code. Like this:
const fs = require('fs');
fs.createReadStream(...)
Copy the code
There are many commonly used built-in modules in Nodejs, as described in the next section
The file search strategy in Node.js’s require method is as follows.
Since there are four types of modules (native module and three types of file module) in Node.js, although the require method is extremely simple, the internal loading is very complicated, and the loading priority is different. As shown in the figure below:
Load from the file module cache
Although native and file modules have different priorities, neither has precedence over loading an existing module from the file module’s cache.
Load from the native module
The priority of the native module is second only to that of the file module cache. The require method preferentially checks whether the module is in the native module list after parsing the file name. HTTP module, for example, in spite of the directory exists an HTTP/HTTP js/HTTP node/HTTP json file, the require (” HTTP “) will not be loaded from the file, but the load from the original module. Native modules also have a cache and are loaded from the cache first. If the cache has not been loaded, the native module’s loading mode is called for loading and execution.
Load from file
When a file module does not exist in the cache and is not a native module, Node.js parses the arguments passed in the require method and loads the actual file from the file system. The packing and compilation details of the loading process were described in the previous section. Here we describe the process of finding the file module in detail. There are also some details worth knowing. The require method accepts the following parameters:
- HTTP, FS, PATH, etc., native module.
- . / mod or.. /mod, relative to the path of the file module.
- /pathtomodule/mod, the absolute pathto the file module.
- Mod, a file module for a non-native module.
Common built-in modules
Fs module
Asynchronous and synchronous
Open the file
fs.open(path, flags[, mode], callback)
Copy the code
parameter
-
Path – The path of the file.
-
Flags – The behavior of file opening. Specific values are described below.
-
Mode – Sets the file mode (permission). The default file creation permission is 0666(readable and writable).
-
Callback – A callback function that takes two arguments such as callback(err, fd).
The flags argument can be one of the following:
Flag describe r Open the file in read mode. Throw an exception if the file does not exist. r+ Open the file in read/write mode. Throw an exception if the file does not exist. rs Read files synchronously. rs+ Read and write files synchronously. w Open file in write mode, create if file does not exist. wx Similar to ‘w’, but if the file path exists, the file fails to be written. w+ Open file in read/write mode, create file if it does not exist. wx+ Similar to ‘w+’, but if the file path exists, the file reads and writes fail. a Open file in append mode, create file if it does not exist. ax Similar to ‘a’, but if the file path exists, file appending fails. a+ Open file in read append mode, create file if it does not exist. ax+ Similar to ‘a+’, but if the file path exists, file read append fails. Written to the file
fs.writeFile(filename, data[, options], callback) Copy the code
If the file exists, what this method writes overwrites the old file.
The parameters are described as follows:
- Path – File path.
- Data – The data to be written to the file, which can be a String or a Buffer object.
- Options – This parameter is an object containing {encoding, mode, flag}. The default encoding is UTf8, the mode is 0666, the flag is ‘w’.
- Callback – The callback function that contains only the error message parameter (err) and is returned when the write fails.
Read the file
fs.read(fd, buffer, offset, length, position, callback) Copy the code
Close the file
fs.close(fd, callback) Copy the code
Capture file
fs.ftruncate(fd, len, callback) Copy the code
The parameters are described as follows:
- Fd – The file descriptor returned by the fs.open() method.
- Len – The length of the truncated file content.
- Callback – A callback function that takes no arguments
Delete the file
fs.unlink(path, callback) Copy the code
The parameters are described as follows:
- Path – File path.
- Callback – A callback function that takes no arguments.
Create a directory
fs.mkdir(path[, mode], callback) Copy the code
-
Path – File path.
-
Mode – Sets the directory permission. The default value is 0777.
-
Callback – A callback function that takes no arguments.
Read the directory
fs.readdir(path, callback) Copy the code
The parameters are described as follows:
- Path – File path.
- Callback – callback function with two parameters, err, files, err is the error information, files is the file array list in the directory
Delete the directory
fs.rmdir(path, callback) Copy the code
The parameters are described as follows:
- Path – File path.
- Callback – A callback function that takes no arguments.
How do I synchronize asynchronous code
-
promise
const {promisify} = require('util'); const readFile = promisify(fs.readFile); readFile('./01-runnode.js').then(data= >console.log(data)); Copy the code
-
Promises API(Node 10.0 +)
const {promises} = require('fs'); promises.readFile('./01-runnode.js').then(data= > console.log(data)); Copy the code
-
generator
const fs = require('fs'); const { promisify } = require('util'); const readFile = promisify(fs.readFile); function* read() { yield readFile('./01-runnode.js'); } let ge = read(); ge.next().value.then(data= >{ console.log(data); }) Copy the code
-
async
const fs = require('fs'); const {promisify} = require('util'); const readFile = promisify(fs.readFile); async function asyncReadFile() { let a = await readFile('./01-runnode.js'); console.log(a.toString()); } asyncReadFile(); Copy the code
File module reference link
OS module
const os = require('os');
// Total system memory
console.log(os.totalmem());
// The amount of free memory in the operating system
console.log(os.freemem());
const mem = os.freemem() / os.totalmem() * 100;
console.log('Memory occupancy${mem}% `);
Copy the code
Using third-party modules
npm i cpu-stat -S
Copy the code
// Use a third-party module
const cpuStat = require('cpu-stat');
cpuStat.usagePercent((err,percent) = >{
console.log(percent);
})
Copy the code
The HTTP module
Nodejs is essentially a Web server, so how do you get the HTTP server to work?
Let’s quickly familiarize ourselves with the simple but not simple HTTP server
const http = require('http');
http.createServer((req,res) = >{
res.end('Response completed');
}).listen(3000);
Copy the code
Starting the server
Browser access :http://localhost:3000 to see the response complete
routing
The simple server above is not sufficient for our needs. For example, we need to access different routing addresses to find different pages. For example:
Visit: http://localhost:3000/index to see the home page content, visit: http://localhost:3000/about to see the content of the about me page
Visit: http://localhost:3000/user to see a json data
const http = require('http');
const fs = require('fs');
http.createServer((req,res) = >{
const {url,method} = req;
if(url === '/index' && method === 'GET') {// Read the home page
fs.readFile('./index.html'.(err,data) = >{
if(err){
res.statusCode = 500;// An internal server error occurred
res.end('500- Interval Serval Error! ');
}
res.statusCode = 200;// Set the status code
res.setHeader('Content-Type'.'text/html'); res.end(data); })}else if(url === '/about' && method ==='GET'){
fs.readFile('./about.html'.(err, data) = > {
if (err) {
res.statusCode = 500;// An internal server error occurred
res.end('500- Interval Serval Error! ');
}
res.statusCode = 200;// Set the status code
res.setHeader('Content-Type'.'text/html'); res.end(data); })}else if(url ==='/user' && method === 'GET'){
res.statusCode = 200;// Set the status code
res.setHeader('Content-Type'.'application/json');
res.end(JSON.stringify([{name:"Little Horse"}]));
}else{
res.end();
}
}).listen(3000);
Copy the code
The Simple version implements its own Express
Create MExpress. Js
const Application = require('./application');
function MExpress() {
return new Application();
}
module.exports = MExpress;
Copy the code
Create application. Js
/ / demand
// 1. Implement the HTTP server
// 2. Implement the GET routing request
const http = require('http');
const url = require('url');
class Application {
constructor() {
this.router = [];
}
get(path, fn) {
this.router.push({
path: path,
method: 'GET'.handle: fn
})
}
listen() {
http.createServer((req, res) = > {
const { pathname } = url.parse(req.url);
for (const route of this.router) {
if (route.path === pathname) {
route.handle(req,res);
return;
}
if(route.path === The '*'){
route.handle(req, res);
return;
}
}
}).listen(...arguments);
}
}
module.exports = Application;
Copy the code
MExpress_test.js
const MExpress = require('./MExpress');
const app = MExpress();
const fs = require('fs');
const path = require('path')
app.get('/index'.(req,res) = >{
fs.readFile('./index.html'.(err, data) = > {
if (err) {
res.statusCode = 500;// An internal server error occurred
res.end('500- Interval Serval Error! ');
}
res.statusCode = 200;// Set the status code
res.setHeader('Content-Type'.'text/html');
res.end(data);
})
})
app.get(The '*'.(req,res) = >{
res.setHeader('Content-Type'.'image/*');
fs.readFile(path.join(__dirname, req.url), function (err, data) {
if (err) {
throw err;
}
res.end(data);
})
})
app.listen(3001);
Copy the code