"Node.js hoạt động dựa trên mô hình hướng sự kiện (Event-Driven). Hiểu EventEmitter là bước quan trọng để xây dựng các ứng dụng bất đồng bộ hiệu quả."
🎯 Mục tiêu bài học
Sau bài này bạn sẽ:
Hiểu Event là gì.
Biết EventEmitter hoạt động như thế nào.
Thành thạo các hàm:
on()once()emit()off()
Truyền dữ liệu qua sự kiện.
Biết cách xây dựng hệ thống Publisher–Subscriber (Pub/Sub) đơn giản.
Event là gì?
Event (Sự kiện) là một hành động xảy ra trong chương trình.
Ví dụ:
Người dùng bấm nút.
File được đọc xong.
Server nhận request.
Timer kết thúc.
Có người đăng nhập.
Khi một sự kiện xảy ra, chương trình có thể thực hiện một hoặc nhiều hành động tương ứng.
EventEmitter là gì?
Node.js cung cấp lớp EventEmitter để:
Phát sự kiện (emit)
Lắng nghe sự kiện (listen)
Import:
import EventEmitter from "node:events";
Tạo đối tượng:
const event = new EventEmitter();
emit()
Phát một sự kiện.
import EventEmitter from "node:events";
const event = new EventEmitter();
event.emit("hello");
Ở ví dụ trên sẽ không có gì xảy ra, vì chưa có ai lắng nghe sự kiện.
on()
Đăng ký lắng nghe sự kiện.
import EventEmitter from "node:events";
const event = new EventEmitter();
event.on("hello", () => {
console.log("Xin chào Node.js");
});
event.emit("hello");
Kết quả
Xin chào Node.js
emit() nhiều lần
event.emit("hello");
event.emit("hello");
event.emit("hello");
↓
Xin chào Node.js
Xin chào Node.js
Xin chào Node.js
Mỗi lần emit() được gọi, tất cả các listener của sự kiện sẽ được thực thi.
once()
Chỉ chạy một lần.
event.once("login", () => {
console.log("Đăng nhập");
});
event.emit("login");
event.emit("login");
event.emit("login");
↓
Đăng nhập
Các lần sau sẽ không chạy nữa.
Truyền dữ liệu
Có thể gửi dữ liệu khi phát sự kiện.
event.on("welcome", (name) => {
console.log(
"Xin chào",
name
);
});
event.emit(
"welcome",
"An"
);
↓
Xin chào An
Nhiều tham số
event.on(
"order",
(
id,
total
) => {
console.log(id);
console.log(total);
}
);
event.emit(
"order",
101,
500000
);
↓
101
500000
Listener
Một sự kiện có thể có nhiều listener.
event.on("save", () => {
console.log("Lưu Database");
});
event.on("save", () => {
console.log("Ghi Log");
});
event.on("save", () => {
console.log("Gửi Email");
});
event.emit("save");
↓
Lưu Database
Ghi Log
Gửi Email
Đây là ưu điểm lớn của lập trình hướng sự kiện: một sự kiện có thể kích hoạt nhiều hành động độc lập.
off()
Xóa listener.
function hello(){
console.log("Hello");
}
event.on(
"test",
hello
);
event.off(
"test",
hello
);
event.emit("test");
↓
Không có kết quả.
removeAllListeners()
Xóa toàn bộ listener.
event.removeAllListeners(
"save"
);
listenerCount()
Đếm listener.
console.log(
event.listenerCount(
"save"
)
);
↓
3
eventNames()
Danh sách các sự kiện.
console.log(
event.eventNames()
);
↓
[
'login',
'save'
]
Ví dụ thực tế
Giả sử người dùng đăng ký tài khoản.
event.on("register", () => {
console.log(
"Lưu Database"
);
});
event.on("register", () => {
console.log(
"Gửi Email"
);
});
event.on("register", () => {
console.log(
"Tạo Log"
);
});
event.emit("register");
↓
Lưu Database
Gửi Email
Tạo Log
Một sự kiện nhưng thực hiện nhiều công việc khác nhau mà các phần của chương trình không cần biết chi tiết về nhau.
Mô hình Publisher–Subscriber
emit()
Publisher
│
▼
EventEmitter
├────────────┐
▼ ▼
Subscriber Subscriber
(Database) (Email)
Publisher chỉ phát sự kiện.
Subscriber chỉ quan tâm đến sự kiện mình đăng ký.
Hai bên không phụ thuộc trực tiếp vào nhau.
Event trong Node.js
Rất nhiều module sử dụng EventEmitter.
Ví dụ
HTTP Server
Streams
File System
Socket.IO
WebSocket
Process
Bạn sẽ gặp EventEmitter rất nhiều khi làm việc với Express, WebSocket và các ứng dụng Realtime.
Ví dụ mini
import EventEmitter from "node:events";
const event =
new EventEmitter();
event.on(
"message",
(text)=>{
console.log(text);
});
event.emit(
"message",
"Hello Node.js"
);
↓
Hello Node.js
Những lỗi thường gặp
emit trước on
Sai
event.emit("hello");
event.on(
"hello",
()=>{
console.log("Hello");
});
↓
Không có kết quả.
Hãy đăng ký listener trước khi phát sự kiện.
Sai tên Event
event.on("save",()=>{});
event.emit("Save");
↓
Không chạy.
Tên sự kiện phân biệt chữ hoa và chữ thường.
Quên xóa Listener
Nếu liên tục thêm listener mà không gỡ bỏ khi không còn cần thiết, ứng dụng có thể tiêu tốn thêm bộ nhớ và Node.js sẽ cảnh báo khi số lượng listener vượt quá ngưỡng mặc định.
Thêm quá nhiều listener
MaxListenersExceededWarning
Có thể xảy ra khi bạn đăng ký quá nhiều listener cho cùng một sự kiện mà không quản lý vòng đời của chúng.
Khi nào nên dùng EventEmitter?
Rất phù hợp cho:
Ghi log.
Gửi email.
Thông báo.
Upload file.
Chat Realtime.
WebSocket.
Plugin.
Hệ thống mở rộng.
Bảng tổng hợp
| Hàm | Ý nghĩa |
|---|---|
emit() | Phát sự kiện |
on() | Lắng nghe sự kiện |
once() | Chỉ chạy một lần |
off() | Gỡ listener |
removeAllListeners() | Xóa tất cả listener |
listenerCount() | Đếm listener |
eventNames() | Danh sách sự kiện |
Tổng kết
Module events là nền tảng của mô hình lập trình hướng sự kiện trong Node.js. Thông qua EventEmitter, bạn có thể phát và lắng nghe các sự kiện, truyền dữ liệu giữa các thành phần và xây dựng các hệ thống linh hoạt theo mô hình Publisher–Subscriber.
Đây là cơ chế được sử dụng rộng rãi trong nhiều module cốt lõi của Node.js và sẽ còn xuất hiện trong các phần Express, WebSocket và Realtime ở các bài học sau.
Bài tiếp theo
👉 Bài 10 — Streams & Buffer
Bạn sẽ học:
Buffer là gì.
Stream là gì.
Readable Stream và Writable Stream.
Pipe dữ liệu giữa các Stream.
Vì sao Stream giúp Node.js xử lý các tệp lớn và dữ liệu truyền tải hiệu quả hơn mà không cần tải toàn bộ vào bộ nhớ.




Không có nhận xét nào:
Đăng nhận xét