Streamovi u Node.js mogu biti komplicirani, ali vrijedi odvojiti malo vremena da ih razumijete.

Ključni zahvati

  • Streamovi u Node.js temeljni su alat za obradu i prijenos podataka, što ih čini idealnim za aplikacije u stvarnom vremenu i aplikacije vođene događajima.
  • Za stvaranje toka koji se može pisati u Node.js, možete koristiti funkciju createWriteStream() modula fs, koja zapisuje podatke na određeno mjesto.
  • Čitljivi, zapisljivi, dvostruki i transformacijski su četiri vrste tokova u Node.js, svaki sa svojim vlastitim slučajem upotrebe i funkcijom.

Tok je temeljni programski alat koji se bavi protokom podataka. U svojoj srži, tok obično predstavlja sekvencijalni prijenos bajtova s ​​jedne točke na drugu. Službena dokumentacija Node.js definira stream kao apstraktno sučelje koje možete koristiti za rad s podacima.

Prijenos podataka na računalu ili preko mreže idealna je upotreba streama.

Streamovi u Node.js

Streamovi su odigrali ključnu ulogu u uspjehu Node.js. Idealni su za obradu podataka u stvarnom vremenu i aplikacije vođene događajima, dvije istaknute značajke Node.js runtime okruženja.

instagram viewer

Da biste stvorili novi stream u Node.js, morat ćete koristiti stream API, koji radi isključivo s nizovima i Podaci međuspremnika Node.js. Node.js ima četiri vrste tokova: za pisanje, za čitanje, dupleks i transformaciju.

Kako stvoriti i koristiti tok za pisanje

Tok koji se može pisati omogućuje pisanje ili slanje podataka na određenu lokaciju. Modul fs (datotečni sustav) ima klasu WriteStream koju možete koristiti za stvaranje novog toka s fs.createWriteStream() funkcija. Ova funkcija prihvaća put do datoteke u koju želite pisati podatke, kao i izborni niz opcija.

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();
})();

Ovaj kod uvozi createWriteStream() funkcija, koja funkcija anonimne strelice zatim koristi za stvaranje toka koji zapisuje podatke u myFile.txt. Anonimna funkcija sadrži unutarnju funkciju tzv pisanje podataka() koji piše podatke.

The createWriteStream() funkcija radi s međuspremnikom za pisanje zbirke brojeva (0–9999) u odredišnu datoteku. Međutim, kada pokrenete gornju skriptu, ona stvara datoteku u istom direktoriju koja sadrži sljedeće podatke:

Trenutna zbirka brojeva završava na 2915, ali je trebala uključivati ​​brojeve do 9999. Do ovog odstupanja dolazi jer svaki WriteStream koristi međuspremnik koji pohranjuje fiksnu količinu podataka odjednom. Da biste saznali koja je ta zadana vrijednost, morat ćete konzultirati highWaterMark opcija.

console.log("The highWaterMark value is: " +
myWriteStream.writableHighWaterMark + " bytes.");

Dodavanje gornjeg retka koda u anonimnu funkciju proizvest će sljedeći izlaz u terminalu:

Izlaz terminala pokazuje da je zadana vrijednost highWaterMark vrijednost (koja se može prilagoditi) je 16,384 bajta. To znači da u ovom međuspremniku možete istovremeno pohraniti samo manje od 16.384 bajta podataka. Dakle, do broja 2,915 (plus svi zarezi i razmaci) predstavlja najveću količinu podataka koju međuspremnik može pohraniti odjednom.

Rješenje pogreške međuspremnika je korištenje događaja toka. Tok se susreće s različitim događajima u različitim fazama procesa prijenosa podataka. The odvoditi događaj je prikladna opcija za ovu situaciju.

u pisanje podataka() funkcija iznad, poziv na WriteStream's write() funkcija vraća true ako je dio podataka (ili interni međuspremnik) ispod highWaterMark vrijednost. To znači da aplikacija može poslati više podataka u stream. Međutim, čim se pisati() funkcija vraća false petlja se prekida jer morate isprazniti međuspremnik.

myWriteStream.on('drain', () => {
console.log("a drain has occurred...");
writeData();
});

Umetanje odvoditi gornji kod događaja u anonimnu funkciju ispraznit će Međuspremnik WriteStreama kada je u kapacitetu. Zatim se prisjeća pisanje podataka() metodu, tako da može nastaviti pisati podatke. Pokretanje ažurirane aplikacije proizvest će sljedeći izlaz:

Trebate imati na umu da je aplikacija morala isprazniti WriteStream međuspremnik tri puta tijekom njegovog izvođenja. Tekstualna datoteka također je doživjela neke promjene:

Kako stvoriti i koristiti čitljiv stream

Za čitanje podataka počnite stvaranjem čitljivog toka pomoću fs.createReadStream() funkcija.

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.");
});
})();

Gornja skripta koristi createReadStream() metoda za pristup datoteci koju je prethodni kod kreirao: myFile.txt. The createReadStream() funkcija prihvaća put datoteke (koji može biti u obliku niza, međuspremnika ili URL-a) i nekoliko izbornih opcija kao argumente.

U anonimnoj funkciji postoji nekoliko važnih stream događaja. Međutim, nema ni traga odvoditi događaj. To je zato što čitljiv tok sprema podatke u međuspremnik samo kada pozovete stream.push (komad) funkcionirati ili koristiti čitljiv događaj.

The otvoren događaj se aktivira kada fs otvori datoteku iz koje želite čitati. Kada priložite podaci događaj na implicitno kontinuirani tok, uzrokuje prijelaz toka u tekući način. To omogućuje prolaz podataka čim postanu dostupni. Pokretanje gornje aplikacije daje sljedeći rezultat:

Kako stvoriti i koristiti dupleksni tok

Dvostruki tok implementira i sučelja toka za pisanje i za čitanje, tako da možete čitati i pisati u takav tok. Jedan primjer je TCP utičnica koja se oslanja na net modul za svoje stvaranje.

Jednostavan način za demonstraciju svojstava dupleksnog toka je stvaranje TCP poslužitelja i klijenta koji prenosi podatke.

Datoteka 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);
});

Datoteka client.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.');
});

Primijetit ćete da i poslužiteljske i klijentske skripte koriste tok koji se može čitati i pisati za komunikaciju (prijenos i primanje podataka). Naravno, poslužiteljska aplikacija se prva pokreće i počinje osluškivati ​​veze. Čim pokrenete klijent, on se povezuje s poslužiteljem pomoću broj TCP priključka.

Nakon uspostavljanja veze, klijent započinje prijenos podataka pisanjem na poslužitelj koristeći svoj WriteStream. Poslužitelj zapisuje podatke koje prima na terminal, a zatim zapisuje podatke koristeći svoj WriteStream. Na kraju, klijent bilježi primljene podatke, upisuje dodatne podatke i zatim prekida vezu s poslužiteljem. Poslužitelj ostaje otvoren za povezivanje drugih klijenata.

Kako stvoriti i koristiti transformacijski tok

Transformacijski tokovi su dvostruki tokovi u kojima je izlaz povezan s ulazom, ali se razlikuje od njega. Node.js ima dvije vrste Transform tokova: zlib i kripto tokove. Zlib tok može komprimirati tekstualnu datoteku i zatim je dekomprimirati nakon prijenosa datoteke.

Aplikacija compressFile.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);
})();

Ova jednostavna skripta uzima izvornu tekstualnu datoteku, sažima je i pohranjuje u trenutni direktorij. Ovo je jednostavan postupak zahvaljujući čitljivim streamovima cijev() metoda. Cjevovodi toka uklanjaju upotrebu međuspremnika i prenose podatke izravno iz jednog toka u drugi.

Međutim, prije nego što podaci dospiju u tok koji se može pisati u skripti, potrebno je malo skrenuti putem zlib-ove metode createGzip(). Ova metoda komprimira datoteku i vraća novi Gzip objekt koji zatim prima tok pisanja.

Aplikacija 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);
})();

Ova gornja skripta uzima komprimiranu datoteku i dekomprimira je. Ako otvorite novi mojaDatoteka2.txt datoteku, vidjet ćete da sadrži iste podatke kao izvorna datoteka:

Zašto su streamovi važni?

Streamovi povećavaju učinkovitost prijenosa podataka. Tokovi koji se mogu čitati i pisati služe kao temelj koji omogućuje komunikaciju između klijenata i poslužitelja, kao i kompresiju i prijenos velikih datoteka.

Streamovi također poboljšavaju performanse programskih jezika. Bez streamova proces prijenosa podataka postaje složeniji, zahtijeva veći ručni unos od strane programera i rezultira većim brojem pogrešaka i problema s izvedbom.