Gran parte dei contenuti di questo corso finora è stata incentrata su concetti quali considerazioni generali sulle prestazioni HTML, suggerimenti sulle risorse, ottimizzazione di vari tipi di risorse per migliorare il tempo di caricamento iniziale della pagina e la reattività all'input dell'utente, nonché il caricamento lento di risorse specifiche.
Tuttavia, c'è un aspetto delle prestazioni relativo a JavaScript che non è ancora stato trattato in questo corso, e questo è il ruolo dei web worker nel migliorare la reattività all'input, di cui si parla in questo modulo e nel modulo successivo.
JavaScript viene spesso descritto come un linguaggio a thread unico. In pratica, questo fa riferimento al thread principale, ovvero l'unico thread in cui il browser esegue la maggior parte del lavoro che vedi nel browser. Questo lavoro include attività relative a elementi come lo scripting, alcuni tipi di operazioni di rendering, l'analisi HTML e CSS e altri tipi di lavori rivolti agli utenti che migliorano l'esperienza utente. In realtà, i browser utilizzano altri thread per svolgere operazioni a cui in genere tu, in qualità di sviluppatore, non disponi dell'accesso diretto, ad esempio i thread GPU.
Per quanto riguarda JavaScript, in genere si lavora sul thread principale, ma solo per impostazione predefinita. È possibile registrare e utilizzare thread aggiuntivi in JavaScript. La funzionalità che consente il multi-threading in JavaScript è nota come API Web Workers.
I web worker sono utili quando hai un lavoro dispendioso in termini di calcolo che non può essere eseguito sul thread principale senza causare attività lunghe che impediscono la risposta della pagina. Queste attività possono certamente influire sull'Interaction to Next Paint (INP) del tuo sito web, perciò può essere utile sapere quando hai un lavoro da eseguire completamente al di fuori del thread principale. Così facendo puoi creare più spazio per altre attività nel thread principale, in modo da velocizzare le interazioni degli utenti.
Questo modulo e la demo successiva che mostra un caso d'uso concreto riguardano i web worker. La demo mostra come utilizzare un web worker per leggere i metadati dell'immagine da un file JPEG al di fuori del thread principale e come far sì che tali metadati vengano riportati nel thread principale affinché l'utente possa vederli.
Come viene lanciato un web worker
Un web worker viene registrato creando un'istanza del classe Worker
. In questo caso devi specificare la posizione del codice del web worker, che viene caricato dal browser e per il quale viene creato successivamente un nuovo thread. Il thread risultante è spesso chiamato thread di lavoro.
const myWebWorker = new Worker('/js/my-web-worker.js');
Nel file JavaScript del worker, in questo caso my-web-worker.js
, puoi scrivere codice che viene quindi eseguito in un thread worker separato.
Limitazioni dei web worker
A differenza di JavaScript che viene eseguito nel thread principale, i web worker non hanno accesso diretto al contesto window
e hanno accesso limitato alle API che forniscono. I web worker sono soggetti ai seguenti vincoli:
- I web worker non possono accedere direttamente al DOM.
- I web worker possono comunicare con il contesto
window
attraverso una pipeline di messaggistica, il che significa che un web worker può accedere indirettamente al DOM in un determinato modo. - L'ambito del web worker è
self
, anzichéwindow
. - L'ambito web worker ha accesso a primitive e costruzioni JavaScript, nonché ad API come
fetch
e a un numero abbastanza elevato di altre API.
In che modo i web worker comunicano con window
Un web worker può comunicare con il contesto window
del thread principale
attraverso una pipeline di messaggistica. Questa pipeline consente di trasferire i dati
da e verso il thread principale e il web worker. Per inviare dati da un web worker al
thread principale, devi configurare un evento message
nel contesto del web worker (self
)
// my-web-worker.js
self.addEventListener("message", () => {
// Sends a message of "Hellow, window!" from the web worker:
self.postMessage("Hello, window!");
});
Quindi, in uno script nel contesto window
nel thread principale, puoi ricevere il messaggio dal thread di worker web utilizzando un altro evento message
:
// scripts.js
// Creates the web worker:
const myWebWorker = new Worker('/js/my-web-worker.js');
// Adds an event listener on the web worker instance that listens for messages:
myWebWorker.addEventListener("message", ({ data }) => {
// Echoes "Hello, window!" to the console from the worker.
console.log(data);
});
La pipeline di messaggistica del web worker è una sorta di escape hatch dal contesto del web worker. Utilizzandolo, puoi inviare dati a window
dal web worker
per aggiornare il DOM oppure eseguire altre operazioni da eseguire sul
thread principale.
verifica le tue conoscenze
Su quale thread viene eseguito un web worker?
A cosa può accedere un web worker?
window
,
tra cui fetch
.
window
, ma solo indirettamente.In che modo un web worker può accedere al contesto "finestra"?
window
.
window
in alcun modo.
postMessage
nel contesto del web worker (self
).
A seguire: un caso d'uso concreto dei web worker
Nel prossimo modulo viene descritto e mostrato in dettaglio un caso d'uso concreto dei web worker. In questo modulo, un web worker viene utilizzato per recuperare un file JPEG da un determinato URL e leggere i relativi metadati Exif in un web worker. Quei dati vengono poi inviati al thread principale per essere mostrati all'utente.