ข้ามไปยังเนื้อหา

Writable Streams

Writable คือ Stream ที่สามารถเขียนข้อมูลเข้าไปได้ ตัวอย่างใน Node ได้แก่ fs.createWriteStream (เขียนไฟล์), process.stdout (แสดงผลที่ Terminal) และ HTTP response object คุณยังสร้าง Writable แบบกำหนดเองได้โดย extend คลาส Writable และ implement method _write

Method หลักสองตัวบน Writable คือ:

  • writable.write(chunk[, encoding][, callback]) — เขียน chunk ข้อมูล คืนค่า true ถ้า internal buffer ต่ำกว่า high-water mark, false ถ้าปลายทางตามไม่ทัน (สัญญาณ backpressure)
  • writable.end([chunk][, callback]) — บอกว่าไม่มีข้อมูลเพิ่มเติมแล้ว เขียน chunk สุดท้ายเพิ่มได้ (optional) และ trigger event finish เมื่อ flush ข้อมูลทั้งหมดแล้ว
const fs = require('node:fs');
const dest = fs.createWriteStream('./output.txt');
dest.write('first line\n');
dest.write('second line\n');
dest.end('last line\n', function() {
console.log('all data flushed');
});

หลังจากเรียก end() และ flush ข้อมูลทั้งหมดไปยัง underlying system แล้ว Stream จะ emit finish นี่คือเวลาที่ถูกต้องเพื่อรู้ว่าการเขียนเสร็จสมบูรณ์จริงๆ:

dest.on('finish', function() {
console.log('write complete');
});

write() คืนค่า boolean เมื่อคืนค่า false internal buffer เต็มแล้ว — คุณต้อง หยุดเขียน และรอ event drain ก่อนจึงเขียนต่อ การเพิกเฉยต่อสัญญาณนี้ทำให้ Memory เติบโตแบบไม่มีขอบเขตเพราะ chunk ที่ Buffer สะสมขึ้นเรื่อยๆ

function writeWithDrain(writable, chunks) {
var i = 0;
function next() {
while (i < chunks.length) {
var ok = writable.write(chunks[i]);
i++;
if (!ok) {
// buffer เต็ม — รอ drain ก่อนต่อ
writable.once('drain', next);
return;
}
}
writable.end();
}
next();
}

นี่คือ pattern แบบ manual ที่ pipe และ pipeline จัดการให้คุณโดยอัตโนมัติ การเข้าใจ pattern นี้อธิบายว่าทำไม API ระดับสูงเหล่านั้นจึงมีอยู่

Demo สร้าง Writable แบบกำหนดเองที่ log แต่ละ chunk ลง Console จำลอง sink ที่ช้า แล้วเขียนข้อมูลสามชุดและปิด Stream

Node.js

Needs the Node.js runtime — open in StackBlitz to run.

writable.write() คืนค่าอะไรเมื่อ internal buffer เต็ม?
Event ใด fire หลังจากเรียก writable.end() และ flush ข้อมูลทั้งหมดแล้ว?
ควรทำอะไรเมื่อ writable.write() คืนค่า false?