Programatorii JavaScript sunt obișnuiți să falsească paralelismul, dar există o modalitate de a obține un paralelism adevărat pe care ar trebui să-l utilizați chiar acum.
JavaScript se poate lupta cu sarcini care necesită performanță, deoarece este un limbaj cu un singur thread. Folosind paralelismul, puteți realiza execuția cu mai multe fire în JavaScript și puteți îmbunătăți performanța și capacitatea de răspuns a aplicațiilor dvs. web moderne.
Paralelism în programarea JavaScript
Paralelismul este crucial în calculul modern pentru îmbunătățirea performanței și scalabilității. Face acest lucru prin utilizarea eficientă a resurselor disponibile.
O tehnică comună folosită pentru a obține paralelismul în programare este multi-threading. Firul JavaScript, totuși, este un sistem cu un singur fir și poate gestiona doar o sarcină la un moment dat. Aceasta înseamnă că nu este familiarizat cu execuțiile programelor paralele.
JavaScript falsează programarea paralelă
O concepție greșită comună despre paralelism este că o puteți realiza folosind
tehnici de programare asincronă cum ar fi asincron/așteptare, apeluri inverse și promisiuni:// Funcție asincronă/așteptă care simulează o solicitare de rețea
asincronfuncţiefetchData() {
const răspuns = asteapta aduce ();
const date = asteapta răspuns.json();
întoarcere date;
}// Funcție de apel invers care înregistrează datele preluate în consolă
funcţielogData(date) {
consolă.log (date);
}// Metoda Promise.all() care execută mai multe promisiuni în paralel
Promisiune.toate([
fetchData(),
fetchData(),
]).apoi((rezultate) => {
consolă.log (rezultate);
});
// Apelați funcția fetchData și transmiteți funcția logData ca apel invers
fetchData().then (logData);
Aceste tehnici nu execută cod în paralel. JavaScript folosește bucla de evenimente pentru a imita programarea paralelă în designul său cu un singur fir.
Bucla de evenimente este o parte fundamentală a mediului de rulare JavaScript. Vă permite să executați operațiuni asincrone, cum ar fi solicitările de rețea, în fundal, fără a bloca firul principal.
Bucla de evenimente verifică în mod constant pentru evenimente sau sarcini noi într-o coadă și le execută unul câte unul secvenţial. Această tehnică permite JavaScript să obțină concurență și paralelism teoretic.
Concurență vs. Paralelism
Concurența și paralelismul sunt adesea greșit înțelese și schimbate în lumea JavaScript.
Concurența în JavaScript se referă la capacitatea de a executa mai multe sarcini prin suprapunerea execuției sarcinilor. Unde o sarcină poate începe înainte ca alta să se finalizeze, dar sarcinile nu pot începe și nici nu se pot termina simultan. Acest lucru permite JavaScript să gestioneze eficient operațiunile, cum ar fi preluarea datelor dintr-un API REST sau citirea fișierelor, fără a bloca firul principal de execuție.
Paralelismul, pe de altă parte, se referă la capacitatea de a executa mai multe sarcini simultan pe mai multe fire. Aceste fire de execuție de fundal pot executa sarcini independent și simultan. Acest lucru deschide oportunități pentru realizarea unui paralelism real în aplicațiile JavaScript.
Aplicațiile JavaScript pot atinge un adevărat paralelism prin utilizarea Web Workers.
Lucrătorii web introduc paralelismul în JavaScript
Lucrătorii web sunt o caracteristică a browserelor web moderne care permit codului JavaScript să ruleze în fire de fundal, separat de firul de execuție principal. Spre deosebire de firul principal, care se ocupă de interacțiunile utilizatorului și actualizările UI. Web Worker-ul va fi dedicat efectuării unor sarcini cu o mare intensitate de calcul.
Mai jos este o reprezentare diagramă a funcționării unui Web Worker în JavaScript.
Firul principal și Web Worker pot comunica prin transmiterea mesajelor. Folosind postMessage metoda de a trimite mesaje și onmessage handler de evenimente pentru a primi mesaje, puteți transmite instrucțiuni sau date înainte și înapoi.
Crearea unui lucrător web
Pentru a crea un Web Worker, trebuie să creați un fișier JavaScript separat.
Iată un exemplu:
// main.js// Creați un nou Web Worker
const muncitor = nou Muncitor(„worker.js”);
// Trimiteți un mesaj către Web Worker
worker.postMessage(„Bună ziua din firul principal!”);
// Ascultați mesajele de la Web Worker
lucrător.onmessage = funcţie(eveniment) {
consolă.Buturuga(„Mesaj primit de la Web Worker:”, eveniment.date);
};
Exemplul de mai sus creează un nou Web Worker trecând calea către scriptul worker (lucrător.js) ca argument la Muncitor constructor. Puteți trimite un mesaj Web Worker folosind postMessage metoda și ascultați mesajele de la Web Worker folosind onmessage organizatorul evenimentului.
Apoi ar trebui să creați scriptul de lucru (lucrător.js) fișier:
// worker.js
// Ascultă mesajele din firul principal
self.onmessage = funcţie(eveniment) {
consolă.Buturuga(„Mesaj primit de la firul principal:”, eveniment.date);
// Trimite un mesaj înapoi la firul principal
self.postMessage(„Salut de la worker.js!”);
};
Scriptul Web Worker ascultă mesajele din firul principal folosind onmessage organizatorul evenimentului. După ce primiți un mesaj, vă deconectați de la mesajul din interior eveniment.date și trimiteți un mesaj nou la firul principal cu postMessage metodă.
Valorificarea paralelismului cu lucrătorii web
Cazul de utilizare principal pentru Web Workers este executarea în paralel a sarcinilor JavaScript intensive din punct de vedere computațional. Prin descărcarea acestor sarcini către Web Workers, puteți obține îmbunătățiri semnificative ale performanței.
Iată un exemplu de utilizare a unui lucrător web pentru a efectua un calcul greu:
// main.jsconst muncitor = nou Muncitor(„worker.js”);
// Trimite date către Web Worker pentru calcul
worker.postMessage([1, 2, 3, 4, 5]);
// Ascultați rezultatul de la Web Worker
lucrător.onmessage = funcţie(eveniment) {
const rezultat = eveniment.date;
consolă.Buturuga(„Rezultatul calculului:”, rezultat);
};
Worker.js:
// Ascultă datele din firul principal
self.onmessage = funcţie (eveniment) {
const numere = eveniment.date;const rezultat = performHeavyCalculation (numere);
// Trimite rezultatul înapoi la firul principal
self.postMessage (rezultat);
};
funcţieefectuați HeavyCalculation(date) {
// Efectuați un calcul complex pe matricea de numere
întoarcere date
.Hartă((număr) =>Matematică.pow (număr, 3)) // Cub fiecare număr
.filtru((număr) => număr % 20) // Filtrați numerele pare
.reduce((sumă, număr) => sumă + număr, 0); // Însumează toate numerele
}
În acest exemplu, treceți o matrice de numere din firul principal către Web Worker. Web Worker efectuează calculul folosind matricea de date furnizată și trimite rezultatul înapoi la firul principal. The performHeavyCalculation() funcția mapează fiecare număr cu cubul său, filtrează numerele pare și, în final, le însumează.
Limitări și considerații
În timp ce lucrătorii web oferă un mecanism pentru realizarea paralelismului în JavaScript, este important să luați în considerare câteva limitări și considerații:
- Fără memorie partajată: Web Workers operează în fire separate și nu partajează memoria cu firul principal. Deci, ei nu pot accesa direct variabile sau obiecte din firul principal fără a trece mesajul.
- Serializare și deserializare: Când treceți date între firul principal și Web Workers, trebuie să serializați și să deserializați datele, deoarece transmiterea mesajelor este o comunicare bazată pe text. Acest proces implică un cost de performanță și poate afecta performanța generală a aplicației.
- Suport pentru browser: Deși Web Workers sunt bine acceptați în majoritatea browserelor web moderne, unele browsere mai vechi sau medii limitate pot avea suport parțial sau deloc pentru Web Workers.
Obțineți paralelismul adevărat în JavaScript
Paralelismul în JavaScript este un concept interesant care permite executarea concomitentă a sarcinilor, chiar și într-un limbaj cu un singur thread. Odată cu introducerea Web Workers, puteți profita de puterea paralelismului și puteți obține îmbunătățiri semnificative ale performanței aplicațiilor dvs. JavaScript.