Node.js Essentials: kiến trúc, Event Loop, REPL, npm và Global Objects
- 22-07-2026
- Toanngo92
- 0 Comments
Node.js không chỉ là “JavaScript chạy trên server”. Để sử dụng hiệu quả, người học cần hiểu cách event loop phối hợp tác vụ, khi nào I/O được chuyển cho hệ điều hành hoặc thread pool, cách thử mã bằng REPL, quản lý package bằng npm và sử dụng các đối tượng toàn cục đúng ngữ cảnh.
Mục lục
1. Kiến trúc Node.js
Mã JavaScript của một tiến trình Node.js thường được thực thi trên một main thread. Event loop theo dõi các callback sẵn sàng chạy và điều phối chúng theo từng giai đoạn. Các thao tác I/O có thể được hệ điều hành xử lý bất đồng bộ; một số công việc khác được chuyển tới thread pool của libuv.

- Call stack: nơi JavaScript đồng bộ đang được thực thi.
- Event loop: quyết định khi nào callback đủ điều kiện được đưa vào thực thi.
- Hệ điều hành: hỗ trợ nhiều thao tác mạng bất đồng bộ.
- libuv thread pool: xử lý một số thao tác như file system, DNS và crypto tùy API.
- Callback/microtask queue: chứa công việc chờ được xử lý theo quy tắc ưu tiên.
“Single-threaded” chỉ mô tả luồng thực thi JavaScript chính. Nó không có nghĩa toàn bộ tiến trình Node.js chỉ sử dụng duy nhất một thread.
2. Luồng xử lý một yêu cầu

- Client gửi request tới ứng dụng Node.js.
- Mã xử lý request chạy trên main thread.
- Nếu gặp I/O bất đồng bộ, Node.js đăng ký công việc với hệ điều hành hoặc libuv rồi tiếp tục xử lý việc khác.
- Khi I/O hoàn tất, callback hoặc Promise reaction được xếp lịch.
- Event loop đưa công việc sẵn sàng trở lại JavaScript khi call stack trống và đến đúng giai đoạn.
Ngược lại, vòng lặp tính toán dài, xử lý ảnh nặng hoặc hàm đồng bộ như một số API *Sync có thể chặn main thread. Khi đó mọi request khác phải chờ dù máy còn nhiều lõi CPU.
3. Lợi ích và giới hạn của Node.js
| Phù hợp | Cần thận trọng |
|---|---|
| REST API và BFF | Tính toán CPU kéo dài |
| Ứng dụng chat, WebSocket | Callback đồng bộ làm việc quá lâu |
| Proxy và streaming | Dùng API file đồng bộ trong request |
| Dịch vụ có nhiều I/O đồng thời | Giữ quá nhiều dữ liệu trong RAM |
Với công việc CPU-bound, có thể sử dụng worker_threads, child process, hàng đợi tác vụ hoặc tách thành dịch vụ riêng. Đừng tăng kích thước thread pool một cách mù quáng: thay đổi này không làm JavaScript trên main thread chạy song song.
4. Chạy tệp JavaScript và dùng REPL
Để chạy một tệp JavaScript:
node app.js
Khi chạy lệnh node không kèm tên tệp, Node.js mở REPL (Read–Eval–Print–Loop). Đây là môi trường tương tác để nhập biểu thức, đánh giá kết quả và thử nhanh API.

node
> const total = [10, 20, 30].reduce((sum, value) => sum + value, 0)
> total
60
> .help
> .exit
REPL phù hợp với đoạn mã ngắn. Với chương trình cần lưu, kiểm thử hoặc tái sử dụng, hãy tạo tệp .js và quản lý bằng Git.
5. Các cấu trúc JavaScript cần thiết
Node.js sử dụng JavaScript, vì vậy kiểu dữ liệu, hàm, object và array đều tuân theo JavaScript. Trong mã mới, ưu tiên const khi không gán lại biến và dùng let khi cần gán lại; hạn chế var do phạm vi function và cơ chế hoisting dễ gây nhầm lẫn.
const student = {
name: 'Lan',
scores: [8, 9, 10],
};
function average(values) {
if (!Array.isArray(values) || values.length === 0) return null;
return values.reduce((sum, value) => sum + value, 0) / values.length;
}
console.log(`${student.name}: ${average(student.scores)}`);
- Primitive: string, number, bigint, boolean, undefined, symbol và null.
- Object: cấu trúc key–value; array và function cũng là object theo nghĩa rộng.
typeof null: trả về"object"vì lý do lịch sử; kiểm tra null bằngvalue === null.- Number: dùng số dấu phẩy động; không nên giả định phép toán thập phân luôn chính xác tuyệt đối.
6. npm và trình quản lý phiên bản Node.js

npm quản lý dependency và script của dự án. NVM hoặc một công cụ quản lý phiên bản khác quản lý chính các phiên bản Node.js. Hai nhóm công cụ này giải quyết hai bài toán khác nhau.
mkdir node-essentials
cd node-essentials
npm init -y
npm install lodash
npm list --depth=0
Mặc định, npm install cài package cục bộ trong dự án và ghi dependency vào package.json. Không chỉnh sửa trực tiếp thư mục node_modules; có thể tái tạo nó bằng lockfile và lệnh npm ci.
- Linux/macOS thường dùng
nvmtừ dự án nvm-sh. - Windows có công cụ riêng như nvm-windows; đây không phải cùng dự án với nvm-sh.
- Luôn kiểm tra tài liệu của công cụ trước khi cài và không chạy script tải từ nguồn không tin cậy.
7. Những global object quan trọng

| API | Mục đích |
|---|---|
console | Ghi thông tin ra stdout và stderr |
process | Đọc tham số, biến môi trường và trạng thái tiến trình |
Buffer | Làm việc với dữ liệu nhị phân |
setTimeout, setInterval | Lập lịch callback theo thời gian |
globalThis | Tham chiếu chuẩn tới global namespace |
require, module, exports, __dirname và __filename trông giống global nhưng thực tế thuộc phạm vi CommonJS module. Trong ES module, hãy dùng import và import.meta phù hợp.
const name = process.argv[2] ?? 'bạn';
const message = Buffer.from(`Xin chào ${name}`, 'utf8');
console.log('Thư mục hiện tại:', process.cwd());
console.log('Số byte:', message.length);
const timer = setTimeout(() => {
console.log(message.toString('utf8'));
}, 500);
// Nếu cần hủy trước khi chạy:
// clearTimeout(timer);
8. Ví dụ về blocking và non-blocking
const fs = require('node:fs');
console.log('Bắt đầu');
fs.readFile('data.txt', 'utf8', (error, data) => {
if (error) {
console.error(error.message);
return;
}
console.log('Số ký tự:', data.length);
});
console.log('Lệnh này thường chạy trước callback readFile');
readFile() đăng ký công việc rồi trả quyền điều khiển, vì vậy dòng cuối không chờ đọc tệp xong. Trong server, cách này giúp main thread tiếp tục phục vụ kết nối khác.
9. Bài tập thực hành
- Mở REPL và thử khai báo object chứa tên, tuổi và kỹ năng.
- Viết hàm tính điểm trung bình từ một array; xử lý trường hợp array rỗng.
- Tạo dự án bằng
npm init -yvà thêm một scriptstart. - Viết chương trình đọc tên từ
process.argvvà in lời chào sau 500 ms. - So sánh thứ tự log giữa mã đồng bộ, Promise,
setTimeoutvà thao tác đọc tệp.
10. Tổng kết
- Event loop điều phối callback; hệ điều hành và libuv hỗ trợ I/O bên dưới.
- Không chặn main thread bằng tính toán dài hoặc API đồng bộ trong luồng request.
- REPL phù hợp để thử nhanh; tệp JavaScript phù hợp với chương trình cần lưu và kiểm thử.
- npm quản lý package, còn NVM và các công cụ tương tự quản lý phiên bản Node.js.
- Phân biệt global thực sự với biến chỉ có trong CommonJS module.

