Streams
Streams trong Node.js
Trong Node.js, Streams là một cơ chế giúp xử lý dữ liệu lớn một cách hiệu quả mà không cần tải toàn bộ dữ liệu vào bộ nhớ. Streams hoạt động theo cơ chế chunk-by-chunk (từng phần nhỏ), giúp tiết kiệm bộ nhớ và tăng tốc độ xử lý.

1. Tổng quan về Streams
Có 4 loại Streams chính trong Node.js:
- Readable Streams – Luồng chỉ đọc (ví dụ: đọc file).
- Writable Streams – Luồng chỉ ghi (ví dụ: ghi file).
- Duplex Streams – Luồng hỗ trợ cả đọc và ghi (ví dụ: socket).
- Transform Streams – Luồng có thể chỉnh sửa dữ liệu trong quá trình truyền (ví dụ: nén dữ liệu).
Streams hoạt động theo hai chế độ:
- Flowing Mode – Dữ liệu được đọc và xử lý ngay lập tức khi có sẵn.
-
Paused Mode – Dữ liệu chỉ được xử lý khi gọi
read()
thủ công.
2. Readable Streams – Đọc dữ liệu từ file
fs.createReadStream()
giúp đọc file theo từng phần nhỏ, thay vì đọc toàn bộ file vào bộ nhớ.
Ví dụ: Đọc file bằng Readable Stream
const fs = require("fs");
// Tạo Readable Stream để đọc file
const readStream = fs.createReadStream("largeFile.txt", { encoding: "utf8" });
// Lắng nghe sự kiện "data" khi có dữ liệu được đọc
readStream.on("data", (chunk) => {
console.log("Đọc được một phần dữ liệu:", chunk);
});
// Lắng nghe sự kiện "end" khi đọc xong
readStream.on("end", () => {
console.log("Đã đọc xong file.");
});
// Lắng nghe sự kiện "error" khi có lỗi
readStream.on("error", (err) => {
console.error("Lỗi khi đọc file:", err);
});
Giải thích:
-
fs.createReadStream()
giúp đọc file mà không cần tải toàn bộ vào bộ nhớ. - Sự kiện
"data"
được kích hoạt khi một phần dữ liệu (chunk) được đọc. - Sự kiện
"end"
báo hiệu quá trình đọc file đã hoàn tất. - Sự kiện
"error"
giúp xử lý lỗi khi đọc file.
3. Writable Streams – Ghi dữ liệu vào file
fs.createWriteStream()
giúp ghi dữ liệu vào file theo từng phần nhỏ.
Ví dụ: Ghi file bằng Writable Stream
const writeStream = fs.createWriteStream("output.txt");
// Ghi dữ liệu vào file
writeStream.write("Dòng 1\n");
writeStream.write("Dòng 2\n");
// Kết thúc Stream
writeStream.end();
// Sự kiện "finish" được gọi khi ghi xong
writeStream.on("finish", () => {
console.log("Ghi file thành công!");
});
// Xử lý lỗi
writeStream.on("error", (err) => {
console.error("Lỗi khi ghi file:", err);
});
Giải thích:
-
fs.createWriteStream()
tạo một Writable Stream để ghi dữ liệu vào file. -
write()
dùng để ghi từng phần dữ liệu. -
end()
kết thúc quá trình ghi. - Sự kiện
"finish"
báo hiệu file đã được ghi thành công. - Sự kiện
"error"
giúp xử lý lỗi.
4. Xử lý file lớn với Streams
Nếu dùng fs.readFile()
, toàn bộ file sẽ được tải vào bộ nhớ, gây lỗi khi file quá lớn. Streams giúp đọc từng phần file mà không tốn quá nhiều RAM.
Ví dụ: Copy file lớn bằng Streams
const readStream = fs.createReadStream("largeFile.txt");
const writeStream = fs.createWriteStream("copy.txt");
// Dùng pipe để truyền dữ liệu từ Readable Stream sang Writable Stream
readStream.pipe(writeStream);
writeStream.on("finish", () => {
console.log("Copy file thành công!");
});
Giải thích:
-
pipe()
giúp truyền dữ liệu từ Readable Stream sang Writable Stream. - Không cần dùng
.on("data")
, vìpipe()
tự động xử lý dữ liệu.
5. Transform Streams – Xử lý dữ liệu khi truyền
Transform Stream
giúp thay đổi dữ liệu khi nó đi qua stream. Ví dụ: chuyển đổi chữ thường thành chữ hoa khi đọc file.
Ví dụ: Chuyển đổi chữ thường thành chữ hoa với Transform Stream
const { Transform } = require("stream");
// Tạo Transform Stream để chuyển chữ thường thành chữ hoa
const upperCaseTransform = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
},
});
// Đọc file, chuyển đổi, rồi ghi vào file mới
fs.createReadStream("input.txt")
.pipe(upperCaseTransform)
.pipe(fs.createWriteStream("output.txt"))
.on("finish", () => console.log("Chuyển đổi thành công!"));
Giải thích:
-
Transform
stream dùng để thay đổi nội dung khi đọc dữ liệu. -
this.push(chunk.toString().toUpperCase())
giúp chuyển đổi dữ liệu sang chữ hoa. -
pipe()
giúp truyền dữ liệu từ Readable Stream → Transform Stream → Writable Stream.
6. Tổng kết
Loại Stream | Chức năng | Ví dụ sử dụng |
---|---|---|
Readable Stream | Đọc dữ liệu theo từng phần nhỏ | fs.createReadStream("file.txt") |
Writable Stream | Ghi dữ liệu theo từng phần nhỏ | fs.createWriteStream("file.txt") |
Duplex Stream | Hỗ trợ cả đọc và ghi | net.Socket (kết nối mạng) |
Transform Stream | Biến đổi dữ liệu khi truyền qua | Chuyển chữ thường thành chữ hoa |
Khi làm việc với file lớn, Streams là một lựa chọn tối ưu để tiết kiệm bộ nhớ và cải thiện hiệu suất.

Với hơn 10 năm kinh nghiệm lập trình web và từng làm việc với nhiều framework, ngôn ngữ như PHP, JavaScript, React, jQuery, CSS, HTML, CakePHP, Laravel..., tôi hy vọng những kiến thức được chia sẻ tại đây sẽ hữu ích và thiết thực cho các bạn.
Xem thêm

Chào, tôi là Vũ. Đây là blog hướng dẫn lập trình của tôi.
Liên hệ công việc qua email dưới đây.
lhvuctu@gmail.com