Home > Article > Web Front-end > An in-depth analysis of the Node.js event loop_node.js
Node.js is a single-process, single-threaded application, but supports concurrency through events and callbacks, so its performance is very high.
(Source: Javascript is single-threaded and asynchronous, but these languages have a common feature: they are event-driven. The events that drive them come from a heterogeneous platform.)
Every API in Node.js is asynchronous and runs as a separate thread, uses asynchronous function calls, and handles concurrency.
Basically all event mechanisms in Node.js are implemented using the observer pattern in the design pattern.
Node.js single thread is similar to entering a while(true) event loop until no event observer exits. Each asynchronous event generates an event observer. If an event occurs, the callback function is called.
Event-driven model
Node.js uses an event-driven model. When the webserver receives a request, it closes it and processes it, and then serves the next web request.
When this request is completed, it is put back into the processing queue, and when the beginning of the queue is reached, the result is returned to the user.
This model is very efficient and scalable because the webserver always accepts requests without waiting for any read or write operations.
(This is also called non-blocking IO or event-driven IO)
In the event-driven model, a main loop is generated to listen for events and trigger a callback function when an event is detected.
This is how the entire event-driven process is implemented, which is very simple. Somewhat similar to the observer pattern, the event is equivalent to a subject (Subject), and all handler functions registered to this event are equivalent to observers (Observer).
Node.js has multiple built-in events. We can bind and listen to events by introducing the events module and instantiating the EventEmitter class, as shown in the following example:
//引入events模块 var events = require('events'); //创建eventEmitter对象 var eventEmitter = new events.EventEmitter(); //创建事件处理程序 var connectHandler = function connected() { console.log('连接成功。'); //触发data_received事件 eventEmitter.emit('data_received'); } //绑定connection事件处理程序 eventEmitter.on('connection', connectHandler); //使用匿名函数绑定data_received事件 eventEmitter.on('data_received', function(){ console.log('数据接收成功。'); }); //触发connection事件 eventEmitter.emit('connection'); console.log("程序执行完毕。");
The output result of the above code is:
Connection successful.
Data received successfully.
The program execution is completed.
The above results are just as you think. Through this event-driven model, we can achieve asynchronous operations.
(For example, we can read the file while executing other commands. After the file reading is completed, we return the file content as a parameter of the callback function. This way there is no blocking or waiting for file I/O while executing the code Operation. This greatly improves the performance of Node.js and can handle a large number of concurrent requests)
.
var fs = require("fs"); fs.readFile('input.txt', function (err, data) { if (err){ console.log(err.stack); return; } console.log(data.toString()); }); console.log("程序执行完毕。");
The output result of the above code is:
The program execution is completed.
Contents of input.txt.
From the above code, we can see that fs.readFile can distribute events. Of course, many objects in Node.js will distribute events. A net.Server object will also distribute an event every time there is a new connection. All of these generate Event objects are instances of events.EventEmitter.
But most of the time we don’t use EventEmitter directly, but inherit it in the object. Including fs, net, http, as long as the core modules that support event response are subclasses of EventEmitter.
Why do you do this? There are two reasons:
First of all, the event implementation of an object with a certain entity function conforms to the semantics. The monitoring and emission of events should be methods of an object.
Secondly, the object mechanism of JavaScript is based on prototype and supports partial multiple inheritance. Inheriting EventEmitter will not disrupt the original inheritance relationship of the object.
Let me share with you my first NodeJs project
There are usually two ways to install Node.js: compiling the source code yourself and using compiled files. I use compiled files here
Currently, I have the node-v4.2.3-linux-x64 I just downloaded in my home directory
1. First decompress
2. Set the link. The purpose of setting the link is that the node command can be used in any path
3. Create a directory called mynodeproj under the home folder, and then create a file called server.js (of course you can also name it another way)
var http = require('http'); http.createServer(function (request, response) { //发送 HTTP 头部 //HTTP 状态值: 200 : OK //内容类型: text/plain response.writeHead(200, {'Content-Type': 'text/plain'}); //发送响应数据 "Hello World" response.end('Hello World\n'); }).listen(8888); //终端打印如下信息 console.log('Server running at http://127.0.0.1:8888/');
4. Use the node command to execute the above code
node server.js
After executing the above command, "Server runnint at http://127.0.0.1:8888/" will be displayed on the command line, which means that the program has been executed successfully!
Because my server is running in Alibaba Cloud, I can access it by just typing Alibaba Cloud IP + port in an external browser.