search
HomeWeb Front-endJS TutorialDetailed explanation of event listening and event publishing usage examples in Node.js

node.js is based on single-threaded non-blocking asynchronous I/O. Asynchronous I/O means that when encountering an I/O operation, the thread does not block but performs the following operations. , then after the I/O operation is completed, how does the thread know that the operation is completed?

When the operation completes the time-consuming I/O operation, the thread of the I/O operation will be notified in the form of an event. The thread will process the event at a specific time and proceed to the next step. Operation, in order to complete asynchronous I/O, the thread must have an event loop mechanism, constantly insisting on whether there are unfinished events, and completing the processing of these events in sequence.

For blocking I/O, when a thread encounters a time-consuming I/O operation, it will stop executing and wait for the operation to be completed. At this time, the thread cannot accept other operation requests. In order to provide throughput, Multiple threads must be created, each thread to respond to a customer's request, but at the same time, only one thread can run on a CPU core. If multiple threads want to execute, they must switch between different threads.

Therefore, node.js reduces the cost of thread creation and thread switching in multi-threads. The cost of thread switching is very high. It needs to allocate memory for it and include it in the schedule. At the same time, when thread switching Sometimes it is necessary to perform memory paging and other operations. These operations can be reduced by using a single thread. However, this programming method also has shortcomings and is not in line with people's design thinking.

node.js is based on the event mode to implement asynchronous I/O. When it is started, it will continuously traverse whether there are any completed events, and then execute them. After the execution is completed, another event will be Notify the thread in the form that this operation has been completed, and this event will be added to the unfinished event list. The thread will traverse this event at some point in the next time and then execute it. In this mechanism, a large event needs to be The tasks are divided into small events, and node.js is also suitable for handling some high I/O and low logic scenarios.

The following example demonstrates asynchronous file reading:


##

var fs = require('fs'); 
fs.readFile('file.txt', 'utf-8', function(err, data) { 
if (err) { 
<span style="white-space:pre"> </span>console.error(err); 
} else { 
<span style="white-space:pre"> </span>console.log(data); 
} 
}); 
[javascript] view plain copy
console.log("end");

Same as above

fs. readFile reads the file asynchronously, and then the process will continue without waiting for it to finish reading the file. When the file is read, an event will be released, and the execution thread will execute the corresponding event when it traverses the event. Operation, here is to execute the corresponding callback function. In the example, the string end will be printed out before the file content.

node.js event API

events.EventEmitter: EventEmitter emits events in node.js with The event listening function provides encapsulation. Each event consists of a string identifying the event name and the corresponding operation.

Event monitoring:


var events = require("events"); 
var emitter = new events.EventEmitter(); 
 <span style="font-family: Arial, Helvetica, sans-serif;">emitter.on("eventName", function(){</span> 
  console.log("eventName事件发生") 
})

Event publishing:


emitter.emit("eventName");

When publishing an event, we can pass in multiple parameters. The first parameter represents the name of the event, and the subsequent parameters represent the incoming parameters. These parameters will be passed into the event. in the callback function.


EventEmitter.once("eventName", listener) : Register a listener for the event that only executes once. When the event occurs for the first time and the listener is triggered, the The listener will be dismissed, and if the event occurs later, the listener will not be executed.

EventEmitter.removeListener(event, listener) :Remove the event listener

EventEmitter.removeAllListeners(event): Remove all event listeners

EventEmitter.setMaxListeners(n): node.js default maximum number of listeners for a single event is 10. If A warning will be given if it exceeds 10. This is done to prevent memory overflow. We can change this limit to another number. If it is set to 0, it means no limit.

EventEmitter.listeners(event) : Returns a list of listeners for an event

Collaboration between multiple events In slightly larger applications, the separation between data and web servers is inevitable, such as Sina Weibo, Facebook, Twitter, etc. The advantage of this is that the data sources are unified, and various rich client programs can be developed for the same data sources.

Taking web applications as an example, when rendering a page, it is usually necessary to pull data from multiple data sources and finally render it to the client. In this scenario, Node.js can naturally and conveniently initiate requests to multiple data sources in parallel at the same time.



api.getUser("username", function (profile) {
 // Got the profile
});
api.getTimeline("username", function (timeline) {
 // Got the timeline
});
api.getSkin("username", function (skin) {
 // Got the skin
});

Node.js uses an asynchronous mechanism to ensure non-blocking between requests, achieve the purpose of parallel requests, and effectively call lower-level resources. However, the problem in this scenario is that coordination of multiple event response results is not elegantly supported natively by Node.js.

In order to obtain results for all three requests before proceeding to the next step, the program may be changed into the following situation:



api.getUser("username", function (profile) {
 api.getTimeline("username", function (timeline) {
  api.getSkin("username", function (skin) {
   // TODO
  });
 });
});

This This will cause requests to be made serially, and the underlying API server cannot be maximized.


为解决这类问题,我曾写作一个模块来实现多事件协作,以下为上面代码的改进版:


var proxy = new EventProxy();
proxy.all("profile", "timeline", "skin", function (profile, timeline, skin) {
 // TODO
});
api.getUser("username", function (profile) {
 proxy.emit("profile", profile);
});
api.getTimeline("username", function (timeline) {
 proxy.emit("timeline", timeline);
});
api.getSkin("username", function (skin) {
 proxy.emit("skin", skin);
});

EventProxy也是一个简单的事件侦听者模式的实现,由于底层实现跟Node.js的EventEmitter不同,无法合并进Node.js中。但是却提供了比EventEmitter更强大的功能,且API保持与EventEmitter一致,与Node.js的思路保持契合,并可以适用在前端中。
这里的all方法是指侦听完profile、timeline、skin三个方法后,执行回调函数,并将侦听接收到的数据传入。

利用事件队列解决雪崩问题

所谓雪崩问题,是在缓存失效的情景下,大并发高访问量同时涌入数据库中查询,数据库无法同时承受如此大的查询请求,进而往前影响到网站整体响应缓慢。

那么在Node.js中如何应付这种情景呢。


var select = function (callback) {
  db.select("SQL", function (results) {
   callback(results);
  });
 };

以上是一句数据库查询的调用,如果站点刚好启动,这时候缓存中是不存在数据的,而如果访问量巨大,同一句SQL会被发送到数据库中反复查询,影响到服务的整体性能。一个改进是添加一个状态锁。


var status = "ready";
var select = function (callback) {
  if (status === "ready") {
   status = "pending";
   db.select("SQL", function (results) {
    callback(results);
    status = "ready";
   });
  }
 };

但是这种情景,连续的多次调用select发,只有第一次调用是生效的,后续的select是没有数据服务的。所以这个时候引入事件队列吧:


var proxy = new EventProxy();
var status = "ready";
var select = function (callback) {
  proxy.once("selected", callback);
  if (status === "ready") {
   status = "pending";
   db.select("SQL", function (results) {
    proxy.emit("selected", results);
    status = "ready";
   });
  }
 };

这里利用了EventProxy对象的once方法,将所有请求的回调都压入事件队列中,并利用其执行一次就会将监视器移除的特点,保证每一个回调只会被执行一次。对于相同的SQL语句,保证在同一个查询开始到结束的时间中永远只有一次,在这查询期间到来的调用,只需在队列中等待数据就绪即可,节省了重复的数据库调用开销。由于Node.js单线程执行的原因,此处无需担心状态问题。这种方式其实也可以应用到其他远程调用的场景中,即使外部没有缓存策略,也能有效节省重复开销。此处也可以用EventEmitter替代EventProxy,不过可能存在侦听器过多,引发警告,需要调用setMaxListeners(0)移除掉警告,或者设更大的警告阀值。

The above is the detailed content of Detailed explanation of event listening and event publishing usage examples in Node.js. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Javascript Data Types : Is there any difference between Browser and NodeJs?Javascript Data Types : Is there any difference between Browser and NodeJs?May 14, 2025 am 12:15 AM

JavaScript core data types are consistent in browsers and Node.js, but are handled differently from the extra types. 1) The global object is window in the browser and global in Node.js. 2) Node.js' unique Buffer object, used to process binary data. 3) There are also differences in performance and time processing, and the code needs to be adjusted according to the environment.

JavaScript Comments: A Guide to Using // and /* */JavaScript Comments: A Guide to Using // and /* */May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript: A Comparative Analysis for DevelopersPython vs. JavaScript: A Comparative Analysis for DevelopersMay 09, 2025 am 12:22 AM

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Python vs. JavaScript: Choosing the Right Tool for the JobPython vs. JavaScript: Choosing the Right Tool for the JobMay 08, 2025 am 12:10 AM

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript: Understanding the Strengths of EachPython and JavaScript: Understanding the Strengths of EachMay 06, 2025 am 12:15 AM

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScript's Core: Is It Built on C or C  ?JavaScript's Core: Is It Built on C or C ?May 05, 2025 am 12:07 AM

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

SublimeText3 English version

SublimeText3 English version

Recommended: Win version, supports code prompts!

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.