de Danny Mcwaves

Cum se utilizează Web Workers pentru a programa sarcini asincrone consistente în JavaScript

Odată cu îmbunătățirile continue aduse motoarelor Javascript și lista în continuă extindere a API-urilor vechi și noi în conformitate cu specificația ECMASCRIPT, căutarea unor aplicații web rapide foarte rapide nu a fost niciodată în creștere.

Ce este motorul Javascript?

Motorul Javascript este o mașină virtuală. A virtual machine se referă la emularea bazată pe software a unui anumit sistem de calcul. Sarcina de bază a unui motor Javascript este să preia codul Javascript pe care îl dezvoltă un dezvoltator și să îl convertească în cod optimizat rapid, care poate fi interpretat de un browser.

Cum se utilizeaza Web Workers pentru a programa sarcini asincrone
Pentru a citi mai multe motoare javascript, consultați motorul javascript v8.

De obicei, acest proces rulează pe un singur fir (mai multe despre fire mai târziu), cu fiecare instrucțiune din codul dezvoltatorului executată pe rând. Problema cu aplicațiile / arhitectura cu un singur fir este că, dacă orice instrucțiune sau bloc de instrucțiuni durează mult timp pentru a fi finalizate, toate instrucțiunile ulterioare închid până când instrucțiunea / blocul de instrucțiuni se termină. Acest lucru este cunoscut sub numele de BLOCKING. Pentru a evita blocarea, un program trebuie să aibă mai multe fire.

Filetat

Un fir este un context de execuție, care reprezintă toate informațiile de care are nevoie un procesor pentru a executa un flux de instrucțiuni.

Să presupunem că citești o carte și vrei să faci o pauză chiar acum, dar vrei să poți reveni și să reiei lectura din punctul exact în care te-ai oprit. O modalitate de a realiza acest lucru este notând numărul paginii, numărul liniei și numărul cuvântului. Deci contextul dvs. de execuție pentru citirea unei cărți sunt aceste trei numere.

Dacă ai o colegă de cameră și folosește aceeași tehnică, poate lua cartea în timp ce tu nu o folosești și poate relua citirea de unde s-a oprit. Apoi, o puteți lua înapoi și o puteți relua de unde ați fost.

Firele funcționează în același mod. Un procesor vă oferă iluzia că face mai multe calcule în același timp. Face acest lucru petrecând puțin timp pe fiecare calcul. Poate face acest lucru deoarece are un context de execuție pentru fiecare calcul.

La fel cum puteți partaja o carte cu prietenul dvs., multe sarcini pot partaja un procesor. Acest proces se numește multi-threading și se rezolvă BLOCKING. Pentru a sprijini multi-threading pe frontend, au fost creați lucrători web.

Cum se utilizeaza Web Workers pentru a programa sarcini asincrone
pentru mai multe despre filetare, vizitați aici.

Lucrători web

1611456909 584 Cum se utilizeaza Web Workers pentru a programa sarcini asincrone
credit de imagine pentru html5schools.

Cea mai simplă utilizare a lucrătorilor este pentru realizarea unei sarcini costisitoare din punct de vedere al calculului, fără a întrerupe interfața cu utilizatorul. (Sursă)

Lucrătorii web permit multi-threading pe front-end generând fire de fundal noi și executând scripturi izolat. Ca urmare, scripturile executate de lucrători trebuie să fie conținute în fișiere separate. Deoarece lucrătorii web execută scripturi în fire izolate, scripturile nu interferează cu firul principal și, prin urmare, nu întrerup interfața de utilizare.

Crearea unui Web Worker

În scop didactic, scriptul extras de mai jos trebuie rulat într-un fir separat.

### fetch.js

self.addEventListener(‘message’,  e => {
    let url = e.data;
    
    fetch(url).then(res => {
        if (res.ok) {
            self.postMessage(res);
        } else {
            throw new Error(’error with server’);
        }
    }).catch(err => {
        self.postMessage(err.message);
    });
})

Worker() apel constructor creează un lucrător și returnează un Worker obiect care reprezintă acel lucrător, care este folosit pentru a comunica cu lucrătorul.

let worker = new Worker('fetch.js');

Constructorul ia numele scriptului ca argument. Dacă fișierul specificat există, lucrătorul generează un fir nou și apoi descarcă și execută complet scriptul. Dacă fișierul nu este disponibil, lucrătorul eșuează în tăcere.

Utilizarea Web Workers

Lucrătorii web comunică cu firul părinte (creatorul lucrătorului) folosind un eveniment model și mesaje. Folosește MessagePort obiecte din spatele scenei și, astfel, acceptă aceleași caracteristici, cum ar fi trimiterea de date structurate și transferul de date binare.

Pentru a primi mesaje de la un lucrător, utilizați onmessage gestionarea evenimentelor pe Worker obiect.

worker.onmessage = (e) => { // block statements }

Puteți utiliza, de asemenea, addEventListener metodă.

worker.addEventListener('message', (e) => { // block statements })

Pentru a primi un mesaj în interiorul lucrătorului, onmessage se folosește metoda de gestionare a evenimentelor.

onmessage = (e) => { // blocks of statements }

Puteți utiliza, de asemenea, un addEventListener metodă exemplificată în fetch.js.

Pentru a trimite date către și de la un lucrător, utilizați postMessage() metodă. Datele structurate precum textul și JSON pot fi trimise pe acest canal de comunicare. Citiți mai multe despre tipurile de date acceptate de messagePort peste aici.

worker.postMessage('some-lousy-data');
// in the parent thread

self.postMessage('some-resulting-data');
// in the worker thread.

Această limitare specială de transmitere a mesajelor este în vigoare din mai multe motive: menține copilul care lucrează în siguranță (deoarece nu poate, în mod flagrant, să afecteze un script părinte) și păstrează pagina părinte fir-sigur (având DOM thread safe ar fi un coșmar logistic pentru dezvoltatorii de browsere).

Încetarea unui lucrător și gestionarea erorilor

Dacă trebuie să terminați imediat un lucrător care rulează din firul principal, puteți face acest lucru apelând metoda de terminare a lucrătorului:

worker.terminate();

În firul lucrătorului, lucrătorii se pot închide apelând propria metodă de închidere:

close();

Firul muncitorului este ucis imediat fără posibilitatea de a-și finaliza operațiunile sau de a curăța după sine.

Erorile de execuție pot fi tratate ascultând în mod explicit un eveniment de eroare care ar putea fi declanșat de Worker obiect.

worker.addEventListener('error', (e) => { // block of statements })

Limitările lucrătorilor web

  1. Toate scripturile web worker trebuie să fie difuzate din același domeniu.
  2. Nu puteți avea acces direct la DOM și la documentul global.
  3. Obiectul fereastră expune API limitat. De exemplu, location și navigator și XMLHttpRequest obiecte.
  4. Acces local restricționat. Lucrătorii web nu lucrează pe fișiere statice. De exemplu file://my/file/on/my/computer.

Dacă utilizați un lucrător pentru a gestiona o sarcină care trebuie în cele din urmă să actualizeze interfața principală a utilizatorului, va trebui să utilizați sistemul de mesagerie pentru a transmite datele între lucrător și aplicația principală. Aplicația principală este apoi responsabilă pentru actualizarea interfeței de utilizare.

În mod similar, dacă lucrătorul dvs. are nevoie de acces la date din document, fereastră sau obiecte părinte, va trebui să le trimiteți în postMessage() apel care este folosit pentru a începe lucrătorul.

Concluzie

Crearea lucrătorilor web va genera fire reale la nivel de sistem de operare care consumă resurse de sistem. Rețineți doar că acest lucru va afecta performanța întregului computer al utilizatorului, nu doar a browserului web. Ca atare, lucrătorii web ar trebui să fie folosiți în mod responsabil și să fie închis atunci când nu mai sunt folosiți pentru a elibera resurse pentru alte aplicații.

Utilizarea lucrătorilor web poate avea un impact semnificativ asupra performanței aplicațiilor web; și aplicațiile mai receptive au un efect bun asupra experienței utilizatorului.

Pentru informații mai detaliate despre lucrătorii web, cum ar fi importarea de scripturi în lucrători și domeniul de aplicare al lucrătorilor web, vă rugăm să vizitați MDN sau WHATWG.

Pentru un exemplu complet funcțional de lucrători web, vizitați aici.