Sự kiện drain
là khi đệm nội bộ một dòng ghi đã bị dọn sạch.
Điều này chỉ có thể xảy ra khi kích thước bộ đệm trong vượt quá thuộc tính highWaterMark
, là byte dữ liệu tối đa có thể được lưu trữ bên trong bộ đệm trong của dòng ghi cho đến khi nó dừng đọc từ nguồn dữ liệu.
Nguyên nhân của một cái gì đó như thế này có thể là do các thiết lập liên quan đến việc đọc nguồn dữ liệu từ một luồng nhanh hơn có thể được ghi vào tài nguyên khác. Ví dụ, có hai con suối:
var fs = require('fs');
var read = fs.createReadStream('./read');
var write = fs.createWriteStream('./write');
Bây giờ tưởng tượng rằng các tập tin read
là trên SSD và có thể đọc ở 500MB/s và write
là trên HDD mà chỉ có thể viết ở 150MB/s
. Luồng ghi sẽ không thể theo kịp và sẽ bắt đầu lưu trữ dữ liệu trong bộ đệm bên trong. Khi bộ đệm đã đạt đến số highWaterMark
, theo mặc định là 16KB, ghi sẽ bắt đầu quay trở lại false
và luồng sẽ xếp hàng nội bộ vào cống. Khi độ dài bộ đệm bên trong là 0, thì sự kiện drain
được kích hoạt.
Đây là cách một cống hoạt động:
if (state.length === 0 && state.needDrain) {
state.needDrain = false;
stream.emit('drain');
}
Và đây là những điều kiện tiên quyết cho một cống mà là một phần của writeOrBuffer
chức năng:
var ret = state.length < state.highWaterMark;
state.needDrain = !ret;
Để xem cách sự kiện drain
được sử dụng, lấy ví dụ từ tài liệu Node.js.
function writeOneMillionTimes(writer, data, encoding, callback) {
var i = 1000000;
write();
function write() {
var ok = true;
do {
i -= 1;
if (i === 0) {
// last time!
writer.write(data, encoding, callback);
} else {
// see if we should continue, or wait
// don't pass the callback, because we're not done yet.
ok = writer.write(data, encoding);
}
} while (i > 0 && ok);
if (i > 0) {
// had to stop early!
// write some more once it drains
writer.once('drain', write);
}
}
}
Mục tiêu của hàm là viết 1.000.000 lần cho luồng có thể ghi. Điều gì xảy ra là biến số ok
được đặt thành true và vòng lặp chỉ thực thi khi ok
là đúng. Đối với mỗi vòng lặp lặp lại, giá trị của ok
được đặt thành giá trị stream.write()
, sẽ trả về false nếu yêu cầu drain
. Nếu ok
trở thành sai, thì trình xử lý sự kiện cho drain
chờ và đang kích hoạt, tiếp tục lại văn bản.
Về mã của bạn, bạn không cần sử dụng sự kiện drain
vì bạn chỉ viết một lần ngay sau khi mở luồng. Vì bạn chưa viết gì lên luồng, bộ đệm bên trong trống, và bạn sẽ phải viết ít nhất 16KB theo khối để sự kiện drain
kích hoạt. Sự kiện drain
là để viết nhiều lần với nhiều dữ liệu hơn cài đặt highWaterMark
của luồng có thể ghi của bạn.
tôi đã chỉnh sửa câu hỏi của mình. – sachin