Web Worker in TypeScript

Web Worker in TypeScript

Dit artikel legt uit wat Web Workers zijn in TypeScript.

Je kunt meer te weten komen over het concept van Web Workers en diverse gebruikstips met voorbeelden.

YouTube Video

Worker in TypeScript

In TypeScript is een Worker een mechanisme voor het uitvoeren van processen op de achtergrond, los van de hoofdthread, gebruikmakend van de JavaScript Web Workers API. Hierdoor kunnen zware berekeningen en asynchrone taken worden uitgevoerd zonder de werking van de gebruikersinterface te beïnvloeden.

Een Worker werkt parallel aan de hoofdthread (UI-thread) en kan gegevens uitwisselen tussen threads via berichten. Zelfs in TypeScript kun je Worker gebruiken terwijl je type-veilige code schrijft.

Basisgebruik van Worker

  1. Een Worker aanmaken

    Maak een Worker-instantie aan en voer het opgegeven script uit. Normaal gesproken wordt het script gedefinieerd in een apart bestand.

  2. Uitwisselen van berichten

    Verzend en ontvang berichten tussen de hoofdthread en de Worker-thread met behulp van postMessage en onmessage.

Voorbeeld: Basisimplementatie van Worker

  1. worker.ts: Script voor Worker
1// worker.ts
2self.onmessage = (event) => {
3    const data = event.data;
4    const result = data.num1 + data.num2;
5    self.postMessage(result); // Return the result to the main thread
6};
  1. main.ts: Script om Worker in hoofdthread te gebruiken
 1// main.ts
 2const worker = new Worker(
 3    new URL('./worker.ts', import.meta.url),
 4    { type: 'module' }
 5);
 6
 7worker.onmessage = (event) => {
 8    console.log("Result from worker:", event.data); // Receive message from the worker
 9};
10
11worker.postMessage({ num1: 10, num2: 20 }); // Send message to the worker
  • In dit voorbeeld draait worker.ts in een aparte thread, berekent de som van num1 en num2, en stuurt dit terug naar de hoofdthread. De hoofdthread ontvangt het resultaat en toont het op de console.
  • Wanneer je type: 'module' opgeeft, wordt het Worker-script geïnterpreteerd als een ES-module, waardoor je import en export kunt gebruiken. Hierdoor kun je module-structuren beheren zonder gebruik te maken van de traditionele importScripts().

Belangrijke punten bij het gebruik van Workers in TypeScript

Type-definities toevoegen

Definieer in TypeScript datatypes om type-veilige interactie tijdens het verzenden en ontvangen van berichten te garanderen.

 1// Define data types
 2interface WorkerData {
 3    num1: number;
 4    num2: number;
 5}
 6
 7interface WorkerResult {
 8    result: number;
 9}
10
11// worker.ts
12self.onmessage = (event: MessageEvent<WorkerData>) => {
13    const data = event.data;
14    const result = data.num1 + data.num2;
15    const message: WorkerResult = { result };
16    self.postMessage(message); // Send the result in a type-safe manner
17};
18
19// main.ts
20const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
21
22// Type the event from the worker
23worker.onmessage = (event: MessageEvent<WorkerResult>) => {
24  console.log("Result from worker:", event.data); // event.data is number
25};
26
27// Send typed data to the worker
28const message: WorkerData = { num1: 10, num2: 20 };
29worker.postMessage(message);
  • Door de typeparameter van MessageEvent op te geven, kun je duidelijk het soort gegevens definiëren dat je wilt ontvangen. Hierdoor kunnen gegevens veilig worden uitgewisseld met typezekerheid.

Het instellen van Webpack of Vite

Bij het gebruik van Worker in TypeScript kunnen bundelprogramma's zoals Webpack of Vite nodig zijn. Met behulp van deze tools kun je het script van de Worker op de juiste manier bundelen en beschikbaar maken vanaf de hoofdthread.

Bijvoorbeeld, bij gebruik van Vite, gebruik import.meta.url om de Worker correct te importeren.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
  • Dit zorgt ervoor dat het gebundelde Worker-script correct wordt geladen, waardoor verwerking met behulp van Worker mogelijk wordt.

Overwegingen voor berichtenuitwisseling en gelijktijdigheid

  1. Data kopiëren

    Bij het verzenden en ontvangen van berichten tussen de hoofdthread en de Worker-thread wordt data gekopieerd. Bij het omgaan met complexe data zoals objecten, moet rekening worden gehouden met efficiëntie. Het vaak uitwisselen van grote hoeveelheden data kan de prestaties verlagen.

  2. Transferable objecten

    Sommige objecten, zoals ArrayBuffer, worden Transferable objecten genoemd. Transferable objecten kunnen naar de Worker worden overgedragen in plaats van gekopieerd tijdens messaging. Dit maakt het mogelijk om de overhead van het kopiëren van data te vermijden.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3const buffer = new ArrayBuffer(1024);
4worker.postMessage(buffer, [buffer]); // Transfer ownership to the Worker
5
6console.log(buffer.byteLength); // 0 (ownership moved)
  • Door [buffer] als tweede argument aan worker.postMessage() door te geven, wordt de buffer naar de Worker overgedragen in plaats van gekopieerd.

  • Hierna wordt de buffer in de hoofdthread leeg (met byteLength 0) en kan deze alleen nog door de Worker gebruikt worden.

Een Worker beëindigen

De Worker moet na gebruik worden beëindigd om het geheugengebruik te minimaliseren. Je kunt een Worker beëindigen door gebruik te maken van de terminate-methode.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2// ...
3
4worker.terminate(); // Terminate the Worker
  • Deze code beëindigt de Worker met behulp van de methode terminate.

Foutenafhandeling in Worker

Als er een fout optreedt binnen een Worker, kun je de fout afhandelen via het onerror-event.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2
3worker.onerror = (error) => {
4    console.error("Error in Worker:", error.message);
5};
  • Deze code vangt en behandelt fouten die binnen de Worker optreden met behulp van het onerror-event.

Samenvatting

Door Worker in TypeScript te gebruiken, kun je zware taken op de achtergrond uitvoeren terwijl de hoofdthread soepel blijft. Door gebruik te maken van type-definities kunnen berichtenuitwisselingen ook op een type-veilige manier worden uitgevoerd. Door aandacht te besteden aan data-uitwisseling en threadbeheer, kun je prestatieverbeteringen en efficiënte gelijktijdigheid bereiken.

Je kunt het bovenstaande artikel volgen met Visual Studio Code op ons YouTube-kanaal. Bekijk ook het YouTube-kanaal.

YouTube Video