JavaScript-medarbejdere: en nybegynder's Guide
i 2019 har internetøkosystemet udviklet sig til det punkt, hvor bro.sereren er et eksekveringsmiljø for applikationer bygget på JavaScript. Dette afspejles i den hastighed, hvormed branchen kommer op med nye rammer, paradigmer, modullæsere og bundlere, afhængighedsledere, bygge værktøjer og pakkeadministratorer år efter år.
da JavaScript blev udtænkt i de tidlige dage af internettet, var retningen for internetudvikling ikke klar. På grund af den konstante, hurtige ændring i branchen og økosystemet, behovet for bagudkompatibilitet mellem BRO.sere og internetstandarder, udviklingen af JavaScript blev en konstant strøm af patches, hacks og eftertanke.
dagens mobile enheder leveres normalt med 8+ CPU-kerner eller 12+ GPU-kerner. Desktop-og server-CPU ‘ er har op til 16 kerner, 32 tråde eller mere.
i dette miljø er det en flaskehals at have et dominerende programmerings-eller scriptmiljø, der er enkelttrådet.
JavaScript er enkelttrådet
dette betyder, at JavaScript — motorer — oprindeligt bro.sere-har en hovedtråd til udførelse, og for at sige det enkelt kan proces eller funktion B ikke udføres, før proces eller funktion A er færdig. En hjemmesides brugergrænseflade reagerer ikke på nogen anden JavaScript-behandling, mens den er optaget af at udføre noget — Dette er kendt som DOM-blokering.
Dette er frygtelig ineffektivt, især sammenlignet med andre sprog.
Hvis vi går til JS Bin og kører denne kode i JavaScript-konsollen:
//noprotecti = 0;while (i < 60000) { console.log("The number is " + i); i++;}
… hele jsbin.com hjemmesiden vil ikke reagere, indtil bro. ser tæller — og logger-til 60.000.
Vi kan ikke interagere med noget på siden, fordi bro.sereren er optaget.
nu er dette en relativt krævende computerproces, og dagens internetapps involverer ofte meget mere krævende opgaver.
vi skal kunne beregne ting i baggrunden, mens brugeren problemfrit interagerer med siden.
Internetarbejdere
V3C offentliggjorde et første udkast til standard for internetarbejdere i 2009. Den fulde specifikation kan findes på hjemmesiden for Hypertekstapplikationsteknologiarbejdsgruppens hjemmeside-eller hvad-et internetstandardorgan alternativ til 3C.
internetarbejdere er et asynkront system eller protokol, hvor hjemmesider kan udføre opgaver i baggrunden uafhængigt af hovedtråden og hjemmesidens brugergrænseflade. Det er et isoleret miljø, der er isoleret fra window
objektet,document
objektet, direkte internetadgang og er bedst egnet til langvarige eller krævende beregningsopgaver.bortset fra internetarbejdere-et system dedikeret til multithreading — er der andre måder at opnå asnykron behandling i JavaScript, f.eks.
for at demonstrere dette vil vi gå tilbage til JS Bin og prøve dette uddrag:
console.log("A");setTimeout(function(){console.log("B");},2000);console.log("C");setTimeout(function(){console.log("D");},0);console.log("E");setTimeout(function(){console.log("F");},1000);
Når vi kører dette, er vores logsekvens A, C, E, D, F, B
. Først skemaer operationer uden timeout, som de kommer, og derefter udfører den setTimeout()
funktioner i rækkefølgen af deres respektive specificerede forsinkelser. Denne asynkronicitet bør dog ikke automatisk sammenflettes med multithreading. Afhængigt af værtsmaskinen kan dette ofte kun være en enkelttråds stak af opkaldene i den rækkefølge, vi forklarede.
Internetarbejdere & Multithreading
som JavaScript-referenceside forklarer, er internetarbejdere et ” middel til, at internetindhold kan køre scripts i baggrundstråde.”
Vi bruger dem på følgende måde: vi kontrollerer tilgængeligheden af Worker()
konstruktøren i Bro.sereren, og hvis den er tilgængelig, instantierer vi et arbejderobjekt med script-URL ‘ en som argument. Dette script udføres på en separat tråd.
scriptet skal serveres fra den samme vært eller domæne af sikkerhedsmæssige årsager, og det er også grunden til, at internetarbejdere ikke fungerer, hvis vi åbner filen lokalt med etfile://
– skema.
if (typeof(Worker) !== "undefined") { worker = new Worker("worker.js");}
nu definerer vi denne kode i worker.js
fil:
i = 0;while (i < 200000) { postMessage("Web Worker Counter: " + i); i++;}
Hvis du vil skrive JavaScript-arbejderfiler af høj kvalitet, skal du tjekke vores bog, JavaScript: Best Practice.
adskillelsen af tråde
en vigtig ting at bemærke her er adskillelsen afwindow
ogdocument
omfanget af udførelse i hovedvinduet tråd, ogworker
omfanget.
for at gøre brug af worker
tråden skal disse to scopes kunne kommunikere. For at opnå dette bruger vi postMessage()
— funktionen i worker.js
— filen-for at sende meddelelser til hovedbrodertråden-og worker.onmessage
lytteren i hovedtråden for at lytte til worker
meddelelser.
Vi kan også sende beskeder fra hovedbrodertråden til worker
tråd eller funktion. Den eneste forskel er, at vi vender ting og kalder worker.postMessage()
på hovedtråden og onmessage
på arbejdstråden. For at citere mosillas udviklerreference:
Bemærk, at
onmessage
ogpostMessage()
skal hænges afWorker
objekt, når det bruges i hovedscripttråden, men ikke når det bruges i arbejderen. Dette skyldes, at arbejdstageren inden for arbejderen faktisk er det globale omfang.
Vi kan brugeterminate()
– metoden på samme måde for at afslutte vores arbejdstagers udførelse.
med alt dette i tankerne kommer vi til dette eksempel:
indeks.html
<!DOCTYPE html><html><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Web Workers Example</title> <style type="text/css"> body {padding-top:28px;} .output-cont {margin-left:12%; margin-top:28px;} .output-cont h3 {width:200px; height:100%;} .output-cont button {padding:4px 8px; font-size:1.1rem; font-family:sans-serif; } </style></head><body><div class="output-cont"><button onclick="testWorker()">start worker</button><h3></h3><button onclick="terminateWorker()">terminate worker</button></div><br/><div class="output-cont"><button onclick="testMainThread()">start blocking thread</button><h3></h3></div><br/><div class="output-cont"><button onclick="alert('browser responsive!')">test browser responsiveness</button></div> <script> var worker; function testWorker() { if (typeof(Worker) !== "undefined") { if (typeof(worker) == "undefined") { worker = new Worker("worker.js"); } worker.onmessage = function(event) { document.getElementById("workerOutput").innerHTML = event.data; }; } else { document.getElementById("workerOutput").innerHTML = "Web Workers are not supported in your browser"; } } function terminateWorker() { worker.terminate(); worker = undefined; } function testMainThread() { for (var i = 0; i < 200000; i++) { document.getElementById("mainThreadOutput").innerHTML = "Main Thread Counter: " + i; } } </script></body></html>
og arbejder.js:
i = 0;while (i < 200000) { postMessage("Web Worker Counter: " + i); i++;}
dette giver os mulighed for at teste virkningerne af udførelse af hovedtråd på sideadfærd og ydeevne i forhold til internetarbejderens effekter.
i denne vejledning brugte vi http-server
til at servere filerne lokalt.
nu kan vi se, at arbejdstråden ikke blokerer interaktiviteten i hovedbro.serprocessen, og at looping gennem 200.000 numre påvirker ikke hovedtråden. Tallene i #workerOutput
elementet opdateres på hver iteration.
den blokerende tråd eller hovedtråden, når den er involveret i en løkke, blokerer al Interaktivitet (Vi har indstillet antallet af iterationer til 200.000 her, men det vil være endnu mere indlysende, hvis vi øger det til 2.000.000).
endnu en ting, der peger os på en blokeret hovedtråd, er, at arbejdsprocessen opdaterer siden på hver iteration, og sløjfen i hovedtråden (den, der er defineret i index.html
) opdaterer kun #mainThreadOutput
elementet på den sidste iteration.
dette skyldes, at bro.ser er for forbrugt med tælling (for
loop) for at kunne tegne DOM, så det gør det kun, når dets forretning medfor
loop er fuldt udført (i slutningen af sløjfen).
konklusion
i denne artikel introducerede vi internetarbejdere, en teknologi, der hjælper internetbranchen med at holde trit med mere og mere krævende internetapps. Dette gøres ved at give en måde for internet apps til at udnytte multi-processor og multi-threaded enheder ved at skænke nogle multi-threaded supermagter til JavaScript.
internetarbejdere forvandler mobile og desktop-miljøer til applikationsplatforme, hvilket giver dem et strengt eksekveringsmiljø. Denne strenghed kan tvinge os til at sørge for kopiering af objekter mellem flere tråde og planlægge vores applikationer med disse begrænsninger i tankerne.