Streaming di Node.js bisa jadi rumit, namun ada baiknya Anda meluangkan waktu untuk memahaminya.
Poin Penting
- Aliran di Node.js adalah alat mendasar untuk pemrosesan dan transfer data, menjadikannya ideal untuk aplikasi real-time dan berbasis peristiwa.
- Untuk membuat aliran yang dapat ditulisi di Node.js, Anda dapat menggunakan fungsi createWriteStream() modul fs, yang menulis data ke lokasi tertentu.
- Dapat dibaca, dapat ditulis, dupleks, dan transformasi adalah empat jenis aliran di Node.js, masing-masing memiliki kasus penggunaan dan fungsionalitasnya sendiri.
Aliran adalah alat pemrograman mendasar yang berhubungan dengan aliran data. Pada intinya, aliran biasanya mewakili transfer berurutan byte dari satu titik ke titik lainnya. Dokumentasi resmi Node.js mendefinisikan aliran sebagai antarmuka abstrak yang dapat Anda gunakan untuk bekerja dengan data.
Mentransfer data pada komputer atau melalui jaringan adalah penggunaan aliran yang ideal.
Streaming di Node.js
Streaming telah memainkan peran penting dalam kesuksesan Node.js. Mereka ideal untuk pemrosesan data real-time dan aplikasi berbasis peristiwa, dua fitur menonjol dari lingkungan runtime Node.js.
Untuk membuat aliran baru di Node.js, Anda harus menggunakan API aliran, yang bekerja secara eksklusif dengan Strings dan Data penyangga Node.js. Node.js memiliki empat jenis aliran: dapat ditulis, dapat dibaca, dupleks, dan transformasi.
Cara Membuat dan Menggunakan Aliran yang Dapat Ditulis
Aliran yang dapat ditulis memungkinkan Anda menulis atau mengirim data ke lokasi tertentu. Modul fs (sistem file) memiliki kelas WriteStream, yang dapat Anda gunakan untuk membuat aliran baru dengan fs.createWriteStream() fungsi. Fungsi ini menerima jalur ke file yang ingin Anda tulis datanya, serta serangkaian opsi opsional.
const {createWriteStream} = require("fs");(() => {
const file = "myFile.txt";
const myWriteStream = createWriteStream(file);
let x = 0;
const writeNumber = 10000;
const writeData = () => {
while (x < writeNumber) {
const chunk = Buffer.from(`${x}, `, "utf-8");
if (x writeNumber - 1) return myWriteStream.end(chunk);
if (!myWriteStream.write(chunk)) break;
x++
}
};
writeData();
})();
Kode ini mengimpor buatWriteStream() fungsi, yang mana fungsi panah anonim kemudian digunakan untuk membuat aliran yang menulis data ke myFile.txt. Fungsi anonim berisi fungsi dalam yang disebut tulisData() yang menulis data.
Itu buatWriteStream() fungsi bekerja dengan buffer untuk menulis kumpulan angka (0–9,999) ke file tujuan. Namun, saat Anda menjalankan skrip di atas, skrip tersebut akan membuat file di direktori yang sama yang berisi data berikut:
Koleksi angka saat ini berakhir pada 2.915, namun seharusnya mencakup angka hingga 9.999. Perbedaan ini terjadi karena setiap WriteStream menggunakan buffer yang menyimpan sejumlah data tetap pada satu waktu. Untuk mempelajari nilai default ini, Anda perlu membaca tanda air tinggi pilihan.
console.log("The highWaterMark value is: " +
myWriteStream.writableHighWaterMark + " bytes.");
Menambahkan baris kode di atas ke fungsi anonim akan menghasilkan keluaran berikut di terminal:
Output terminal menunjukkan bahwa default tanda air tinggi nilai (yang dapat disesuaikan) adalah 16.384 byte. Artinya, Anda hanya dapat menyimpan data berukuran kurang dari 16.384 byte dalam buffer ini dalam satu waktu. Jadi, hingga angka 2.915 (ditambah semua koma dan spasi) mewakili jumlah maksimum data yang dapat disimpan buffer pada satu waktu.
Solusi untuk kesalahan buffer adalah dengan menggunakan acara streaming. Aliran menghadapi berbagai peristiwa pada tahap berbeda dari proses transfer data. Itu mengeringkan event adalah pilihan yang cocok untuk situasi ini.
Dalam tulisData() fungsi di atas, panggilan ke Tulisan WriteStream() fungsi mengembalikan nilai true jika potongan data (atau buffer internal) berada di bawah tanda air tinggi nilai. Hal ini menunjukkan bahwa aplikasi dapat mengirimkan lebih banyak data ke aliran. Namun, begitu menulis() fungsi mengembalikan false loop terputus karena Anda perlu menguras buffer.
myWriteStream.on('drain', () => {
console.log("a drain has occurred...");
writeData();
});
Memasukkan mengeringkan kode peristiwa di atas ke dalam fungsi anonim akan mengosongkan penyangga WriteStream ketika sudah mencapai kapasitasnya. Kemudian, ia mengingat kembali tulisData() metode, sehingga dapat terus menulis data. Menjalankan aplikasi yang diperbarui akan menghasilkan keluaran berikut:
Anda harus mencatat bahwa aplikasi harus menguras Penyangga WriteStream tiga kali selama pelaksanaannya. File teks juga mengalami beberapa perubahan:
Cara Membuat dan Menggunakan Aliran yang Dapat Dibaca
Untuk membaca data, mulailah dengan membuat aliran yang dapat dibaca menggunakan fs.createReadStream() fungsi.
const {createReadStream} = require("fs");
(() => {
const file = "myFile.txt";
const myReadStream = createReadStream(file);myReadStream.on("open", () => {
console.log(`The read stream has successfully opened ${file}.`);
});myReadStream.on("data", chunk => {
console.log("The file contains the following data: " + chunk.toString());
});
myReadStream.on("close", () => {
console.log("The file has been successfully closed.");
});
})();
Script di atas menggunakan buatReadStream() metode untuk mengakses file yang dibuat kode sebelumnya: myFile.txt. Itu buatReadStream() fungsi menerima jalur file (yang dapat berupa string, buffer, atau URL) dan beberapa opsi opsional sebagai argumen.
Dalam fungsi anonim, ada beberapa peristiwa aliran penting. Namun, belum ada tanda-tandanya mengeringkan peristiwa. Hal ini karena aliran yang dapat dibaca hanya mem-buffer data saat Anda memanggil stream.push (potongan) berfungsi atau menggunakan dapat dibaca peristiwa.
Itu membuka acara menyala ketika fs membuka file yang ingin Anda baca. Saat Anda melampirkan data peristiwa ke aliran yang secara implisit terus-menerus, hal ini menyebabkan aliran tersebut bertransisi ke mode mengalir. Hal ini memungkinkan data untuk melewatinya segera setelah tersedia. Menjalankan aplikasi di atas akan menghasilkan keluaran sebagai berikut:
Cara Membuat dan Menggunakan Aliran Dupleks
Aliran dupleks mengimplementasikan antarmuka aliran yang dapat ditulis dan dibaca, sehingga Anda dapat membaca dan menulis ke aliran tersebut. Salah satu contohnya adalah soket TCP yang mengandalkan modul net untuk pembuatannya.
Cara sederhana untuk mendemonstrasikan properti aliran dupleks adalah dengan membuat server TCP dan klien yang mentransfer data.
File server.js
const net = require('net');
const port = 5000;
const host = '127.0.0.1';const server = net.createServer();
server.on('connection', (socket)=> {
console.log('Connection established from client.');socket.on('data', (data) => {
console.log(data.toString());
});socket.write("Hi client, I am server " + server.address().address);
socket.on('close', ()=> {
console.log('the socket is closed')
});
});
server.listen(port, host, () => {
console.log('TCP server is running on port: ' + port);
});
File klien.js
const net = require('net');
const client = new net.Socket();
const port = 5000;
const host = '127.0.0.1';client.connect(port, host, ()=> {
console.log("connected to server!");
client.write("Hi, I'm client " + client.address().address);
});client.on('data', (data) => {
console.log(data.toString());
client.write("Goodbye");
client.end();
});
client.on('end', () => {
console.log('disconnected from server.');
});
Anda akan melihat bahwa skrip server dan klien menggunakan aliran yang dapat dibaca dan ditulis untuk berkomunikasi (mentransfer dan menerima data). Secara alami, aplikasi server berjalan terlebih dahulu dan mulai mendengarkan koneksi. Segera setelah Anda memulai klien, ia terhubung ke server menggunakan nomor port TCP.
Setelah membuat koneksi, klien memulai transfer data dengan menulis ke server menggunakan miliknya Aliran Tulis. Server mencatat data yang diterimanya ke terminal, lalu menulis data menggunakan WriteStream-nya. Terakhir, klien mencatat data yang diterimanya, menulis data tambahan, dan kemudian memutuskan sambungan dari server. Server tetap terbuka untuk klien lain untuk terhubung.
Cara Membuat dan Menggunakan Aliran Transformasi
Aliran transformasi adalah aliran dupleks yang keluarannya berhubungan dengan, namun berbeda dengan masukan. Node.js memiliki dua jenis aliran Transformasi: aliran zlib dan kripto. Aliran zlib dapat mengompresi file teks dan kemudian mendekompresinya setelah transfer file.
Aplikasi kompresFile.js
const zlib = require('zlib');
const { createReadStream, createWriteStream } = require('fs');(() => {
const source = createReadStream('myFile.txt');
const destination = createWriteStream('myFile.txt.gz');
source.pipe(zlib.createGzip()).pipe(destination);
})();
Skrip sederhana ini mengambil file teks asli, mengompresnya, dan menyimpannya di direktori saat ini. Ini adalah proses yang sederhana berkat aliran yang dapat dibaca pipa() metode. Alur aliran menghilangkan penggunaan buffer dan menyalurkan data secara langsung dari satu aliran ke aliran lainnya.
Namun, sebelum data mencapai aliran yang dapat ditulis dalam skrip, diperlukan sedikit jalan memutar melalui metode createGzip() zlib. Metode ini mengompresi file dan mengembalikan objek Gzip baru yang kemudian diterima oleh aliran tulis.
Aplikasi decompressFile.js
const zlib = require('zlib');
const { createReadStream, createWriteStream } = require('fs');
(() => {
const source = createReadStream('myFile.txt.gz');
const destination = createWriteStream('myFile2.txt');
source.pipe(zlib.createUnzip()).pipe(destination);
})();
Skrip di atas mengambil file terkompresi dan mendekompresinya. Jika Anda membuka yang baru File2.txt saya file, Anda akan melihat bahwa file tersebut berisi data yang sama dengan file aslinya:
Mengapa Streaming Penting?
Streaming meningkatkan efisiensi transfer data. Aliran yang dapat dibaca dan ditulis berfungsi sebagai landasan yang memungkinkan komunikasi antara klien dan server, serta kompresi dan transfer file besar.
Streaming juga meningkatkan kinerja bahasa pemrograman. Tanpa aliran, proses transfer data menjadi lebih kompleks, memerlukan lebih banyak masukan manual dari pengembang dan mengakibatkan lebih banyak kesalahan dan masalah kinerja.