Web Worker en TypeScript

Web Worker en TypeScript

Cet article explique les Web Workers en TypeScript.

Vous pouvez en apprendre davantage sur le concept des Web Workers et découvrir divers conseils d'utilisation avec des exemples.

YouTube Video

Worker en TypeScript

En TypeScript, un Worker est un mécanisme permettant d'exécuter des traitements en arrière-plan, séparément du thread principal, en utilisant l'API des Web Workers de JavaScript. Cela permet d'exécuter des calculs lourds et des tâches asynchrones sans affecter le fonctionnement de l'interface utilisateur.

Un Worker fonctionne en parallèle avec le thread principal (thread de l'interface utilisateur) et peut échanger des données entre les threads via des messages. Même en TypeScript, vous pouvez utiliser un Worker tout en écrivant du code avec typage sécurisé.

Utilisation de base d'un Worker

  1. Créer un Worker

    Créez une instance de Worker et exécutez le script spécifié. Normalement, le script est défini dans un fichier séparé.

  2. Échange de messages

    Envoyez et recevez des messages entre le thread principal et le thread Worker en utilisant postMessage et onmessage.

Exemple : Implémentation de base d'un Worker

  1. worker.ts : Script pour le 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 pour utiliser un Worker dans le thread principal
 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
  • Dans cet exemple, worker.ts s'exécute dans un thread séparé, calcule la somme de num1 et num2, et la renvoie au thread principal. Le thread principal reçoit le résultat et l'affiche dans la console.
  • Lorsque vous spécifiez type: 'module', le script Worker est interprété comme un module ES, ce qui vous permet d'utiliser import et export. Cela vous permet de gérer les structures de modules sans utiliser le traditionnel importScripts().

Points à considérer lors de l'utilisation des Workers en TypeScript

Ajout de définitions de types

En TypeScript, définissez des types de données pour garantir une interaction sécurisée par typage lors de l'envoi et de la réception des messages.

 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);
  • En spécifiant le paramètre de type de MessageEvent, vous pouvez définir clairement le type de données à recevoir. Cela permet d'échanger des données en toute sécurité de type.

Configurer Webpack ou Vite

Lors de l'utilisation de Worker en TypeScript, des outils comme Webpack ou Vite peuvent être nécessaires. En utilisant ces outils, vous pouvez correctement empaqueter le script Worker et le rendre disponible depuis le thread principal.

Par exemple, en utilisant Vite, utilisez import.meta.url pour importer correctement le Worker.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
  • Cela garantit que le script Worker empaqueté est chargé correctement, permettant un traitement profitant du Worker.

Considérations sur la messagerie et la concurrence

  1. Copie des données

    Lors de l'envoi et de la réception de messages entre le thread principal et le thread Worker, les données sont copiées. Lorsqu'il s'agit de données complexes telles que des objets, l'efficacité doit être prise en compte. L'échange fréquent de grandes quantités de données peut nuire aux performances.

  2. Objets Transferable

    Certains objets, tels que ArrayBuffer, sont appelés objets Transferable. Les objets Transferable peuvent être transférés au Worker au lieu d'être copiés lors de la messagerie. Cela vous permet d'éviter le surcoût lié à la copie des données.

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)
  • En passant [buffer] comme second argument à worker.postMessage(), le buffer est transféré au Worker au lieu d'être copié.

  • Après cela, le buffer sur le thread principal devient vide (avec une byteLength de 0) et ne peut être utilisé que par le Worker.

Terminer un Worker

Le Worker doit être terminé après utilisation pour minimiser la consommation de mémoire. Vous pouvez terminer un Worker en utilisant la méthode terminate.

1const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
2// ...
3
4worker.terminate(); // Terminate the Worker
  • Ce code termine le Worker en utilisant la méthode terminate.

Gestion des exceptions dans un Worker

Si une erreur se produit dans un Worker, vous pouvez gérer l'erreur à l'aide de l'événement onerror.

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};
  • Ce code intercepte et gère les erreurs survenant à l'intérieur du Worker grâce à l'événement onerror.

Résumé

En utilisant Worker avec TypeScript, vous pouvez exécuter des tâches lourdes en arrière-plan tout en maintenant le thread principal fluide. En utilisant des définitions de type, les échanges de messages peuvent également être effectués de manière sécurisée en termes de types. En prêtant attention à l'échange de données et à la gestion des threads, vous pouvez améliorer les performances et obtenir une concurrence efficace.

Vous pouvez suivre l'article ci-dessus avec Visual Studio Code sur notre chaîne YouTube. Veuillez également consulter la chaîne YouTube.

YouTube Video