Understanding events and event loop in nodejs
Related recommendations: "nodejs Tutorial"
Friends who are familiar with javascript should have used events, such as mouse movement, mouse click, Keyboard input and so on. We listen to these events in javascript to trigger corresponding processing.
There are also events in nodejs, and there is also a special events module for specialized processing.
Simultaneous events and event loops are also very important concepts for building asynchronous IO in nodejs.
Today we will learn more about it.
Events
nodejs provides a special module for events: lib/events.js.
Remember when we were talking about using nodejs to build a web server?
const server = http.createServer((req, res) => { res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('welcome to www.flydean.com\n') })
Here, each request will trigger the request event.
The core API of nodejs is based on asynchronous event-driven architecture, so there are a lot of events in nodejs.
For example: net.Server will trigger an event every time there is a new connection, fs.ReadStream will trigger an event when a file is opened, and stream will trigger an event when the data is readable.
Let’s take a look at how to build a nodejs event:
const EventEmitter = require('events') const eventEmitter = new EventEmitter()
There are two commonly used methods for events, namely on and emit.
on is used to listen for events, and emit is used to trigger events.
eventEmitter.on('fire', () => { console.log('开火') }) eventEmitter.emit('fire')
emit can also take parameters. Let’s look at the next parameter:
eventEmitter.on('fire', who => { console.log(`开火 ${who}`) }) eventEmitter.emit('fire', '美帝')
Let’s look at the two parameters:
eventEmitter.on('fire', (who, when) => { console.log(`开火 ${who} ${when}`) }) eventEmitter.emit('fire', '川建国','now')
By default, EventEmitter starts with All listeners are called synchronously in the order they were registered. This ensures correct ordering of events and helps avoid race conditions and logic errors.
If asynchronous execution is required, you can use setImmediate() or process.nextTick() to switch to asynchronous execution mode.
eventEmitter.on('fire', (who, when) => { setImmediate(() => { console.log(`开火 ${who} ${when}`); }); }) eventEmitter.emit('fire', '川建国','now')
In addition, events also support several other methods:
once(): Add a single listener
removeListener() / off(): From Remove event listeners from events
removeAllListeners(): Remove all event listeners
Event loop
We know that nodejs code runs in a single-threaded environment Yes, only one thing will be dealt with at a time.
This processing method avoids the problem of data synchronization in a multi-threaded environment and greatly improves processing efficiency.
The so-called event loop means that in a program cycle, after the processor has processed the events of this cycle, it will enter the next event cycle and process the events of the next event cycle. This is a cycle after cycle. .
Blocking of event loop
If the processing of an event is blocked during event processing, it will affect the execution of other events, so we can see that in JS , almost all IO is non-blocking. This is also why there are so many callbacks in JavaScript.
Event loop example
Let’s look at a simple event loop example:
const action2 = () => console.log('action2') const action3 = () => console.log('action3') const action1 = () => { console.log('action1') action2() action3() } action1()
The above code output:
action1 action2 action3
Stack and message queue
We know that calls between functions are implemented through the stack. In the above example, our calling sequence is also implemented through the stack.
But not all methods in the function will be pushed onto the stack, and some methods will be put into the message queue.
Let’s give another example:
const action2 = () => console.log('action2') const action3 = () => console.log('action3') const action1 = () => { console.log('action1') setTimeout(action2, 0) action3() } action1()
The result of running the above code is:
action1 action3 action2
The result is different. This is because settimeout triggers the timer. When the timer expires, the callback function will be placed in the message queue to be processed instead of being placed on the stack.
The event loop will prioritize events in the stack. Only when there is no data in the stack will it switch to consuming events in the message queue.
Although the timeout time of setTimeout in the above example is 0, it still has to wait until action3 is executed before it can be executed.
Note that the timeout in setTimeout does not wait in the current thread. It is called by the browser or other JS execution environment.
Job queue and promise
Promise in ES6 introduces the concept of job queue. Using the job queue will execute the result of the asynchronous function as soon as possible instead of placing it at the end of the call stack.
For example:
const action2 = () => console.log('action2') const action3 = () => console.log('action3') const action1 = () => { console.log('action1') setTimeout(action2, 0) new Promise((resolve, reject) => resolve('应该在action3之后、action2之前') ).then(resolve => console.log(resolve)) action3() } action1()
Output result:
action1 action3 应该在action3之后、action2之前 action2
This is because the Promise resolved before the end of the current function will be executed immediately after the current function.
That is to say, the stack is executed first, then the job queue is executed, and finally the message queue is executed.
process.nextTick()
Let me first give you a definition called tick. A tick refers to an event cycle. Process.nextTick() refers to calling this function before the next event loop tick starts:
process.nextTick(() => { console.log('i am the next tick'); })
So nextTick must be faster than the setTimeout of the message queue.
setImmediate()
nodejs provides a setImmediate method to execute code as quickly as possible.
setImmediate(() => { console.log('I am immediate!'); })
The function in setImmediate will be executed in the next iteration of the event loop.
The functions of setImmediate() and setTimeout(() => {}, 0) are basically similar. They will all be run on the next iteration of the event loop.
setInterval()
If you want to execute certain callback functions regularly, you need to use setInterval.
setInterval(() => { console.log('每隔2秒执行一次'); }, 2000)
要清除上面的定时任务,可以使用clearInterval:
const id = setInterval(() => { console.log('每隔2秒执行一次'); }, 2000) clearInterval(id)
注意,setInterval是每隔n毫秒启动一个函数,不管该函数是否执行完毕。
如果一个函数执行时间太长,就会导致下一个函数同时执行的情况,怎么解决这个问题呢?
我们可以考虑在回调函数内部再次调用setTimeout,这样形成递归的setTimeout调用:
const myFunction = () => { console.log('做完后,隔2s再次执行!'); setTimeout(myFunction, 2000) } setTimeout(myFunction, 2000)
更多编程相关知识,请访问:编程视频!!
The above is the detailed content of Understanding events and event loop in nodejs. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Summary: Asynchronous programming in C++ allows multitasking without waiting for time-consuming operations. Use function pointers to create pointers to functions. The callback function is called when the asynchronous operation completes. Libraries such as boost::asio provide asynchronous programming support. The practical case demonstrates how to use function pointers and boost::asio to implement asynchronous network requests.

The event-driven mechanism in concurrent programming responds to external events by executing callback functions when events occur. In C++, the event-driven mechanism can be implemented with function pointers: function pointers can register callback functions to be executed when events occur. Lambda expressions can also implement event callbacks, allowing the creation of anonymous function objects. The actual case uses function pointers to implement GUI button click events, calling the callback function and printing messages when the event occurs.

3 common problems and solutions in asynchronous programming in Java frameworks: Callback Hell: Use Promise or CompletableFuture to manage callbacks in a more intuitive style. Resource contention: Use synchronization primitives (such as locks) to protect shared resources, and consider using thread-safe collections (such as ConcurrentHashMap). Unhandled exceptions: Explicitly handle exceptions in tasks and use an exception handling framework (such as CompletableFuture.exceptionally()) to handle exceptions.

The Go framework uses Go's concurrency and asynchronous features to provide a mechanism for efficiently handling concurrent and asynchronous tasks: 1. Concurrency is achieved through Goroutine, allowing multiple tasks to be executed at the same time; 2. Asynchronous programming is implemented through channels, which can be executed without blocking the main thread. Task; 3. Suitable for practical scenarios, such as concurrent processing of HTTP requests, asynchronous acquisition of database data, etc.

jQuery is a popular JavaScript library that can be used to simplify DOM manipulation, event handling, animation effects, etc. In web development, we often encounter situations where we need to change event binding on select elements. This article will introduce how to use jQuery to bind select element change events, and provide specific code examples. First, we need to create a dropdown menu with options using labels:

1. Why use asynchronous programming? Traditional programming uses blocking I/O, which means that the program waits for an operation to complete before continuing. This may work well for a single task, but may cause the program to slow down when processing a large number of tasks. Asynchronous programming breaks the limitations of traditional blocking I/O and uses non-blocking I/O, which means that the program can distribute tasks to different threads or event loops for execution without waiting for the task to complete. This allows the program to handle multiple tasks simultaneously, improving the program's performance and efficiency. 2. The basis of Python asynchronous programming The basis of Python asynchronous programming is coroutines and event loops. Coroutines are functions that allow a function to switch between suspending and resuming. The event loop is responsible for scheduling

The advantages of asynchronous programming in PHP include higher throughput, lower latency, better resource utilization, and scalability. Disadvantages include complexity, difficulty in debugging, and limited library support. In the actual case, ReactPHP is used to handle WebSocket connections, demonstrating the practical application of asynchronous programming.

Methods for building event-based applications in PHP include using the EventSourceAPI to create an event source and using the EventSource object to listen for events on the client side. Send events using Server Sent Events (SSE) and listen for events on the client side using an XMLHttpRequest object. A practical example is to use EventSource to update inventory counts in real time in an e-commerce website. This is achieved on the server side by randomly changing the inventory and sending updates, and the client listens for inventory updates through EventSource and displays them in real time.
