API des Web Workers HTML

-

Bases des Web Workers

Les bases des Web Workers couvrent les concepts de création, de communication et de terminaison des Web Workers. Pour créer un Web Worker, vous spécifiez le fichier script contenant le code du worker. La communication entre le script principal et le Web Worker se fait par passage de messages, en utilisant la méthode postMessage() pour envoyer des messages et le gestionnaire d'événements onmessage pour recevoir des messages. Lorsqu'un Web Worker n'est plus nécessaire, vous pouvez le terminer en utilisant la méthode terminate().

Types de Web Workers

Type Description
Workers dédiés Les Workers dédiés sont le type de Web Worker le plus courant. Ils sont associés à un seul script et ne peuvent communiquer qu'avec ce script. Les Workers dédiés sont créés en utilisant le constructeur Worker et sont utiles pour décharger les tâches intensives en CPU spécifiques à un script particulier.
Workers partagés Les Workers partagés permettent à plusieurs scripts, même de différentes fenêtres ou iframes, de communiquer avec un seul worker. Ils sont créés en utilisant le constructeur SharedWorker. Les Workers partagés sont utiles pour les tâches qui doivent être partagées entre plusieurs scripts ou fenêtres, comme la gestion d'un cache partagé ou la fourniture d'un canal de communication centralisé.
Service Workers Les Service Workers sont un type spécial de Web Worker qui agissent comme un proxy entre les applications web, le navigateur et le réseau. Ils sont conçus pour intercepter les requêtes réseau, mettre en cache les ressources et fournir des fonctionnalités hors ligne. Les Service Workers ont un cycle de vie différent et sont créés en utilisant la méthode navigator.serviceWorker.register(). Ils sont couramment utilisés pour créer des Applications Web Progressives (PWA) et améliorer les performances des applications web.

Chaque type de Web Worker a son propre cas d'utilisation spécifique et son modèle de communication. Les Workers dédiés sont le type le plus simple, tandis que les Workers partagés et les Service Workers offrent des fonctionnalités plus avancées pour des scénarios spécifiques. Comprendre les différences entre ces types de Web Workers est important pour choisir celui qui convient à vos besoins et les implémenter correctement dans votre application web.

Utilisation des Web Workers

Les Web Workers offrent un mécanisme pour décharger les tâches gourmandes en CPU, exécuter des tâches en arrière-plan et gérer les scripts de longue durée sans bloquer le fil d'exécution principal. En utilisant les Web Workers, vous pouvez améliorer les performances et la réactivité de vos applications web.

Un cas d'utilisation des Web Workers est le déchargement des tâches gourmandes en CPU. Lorsque vous avez des opérations nécessitant beaucoup de calculs, comme des algorithmes complexes, du traitement d'images ou de l'analyse de données, vous pouvez déplacer ces tâches vers un Web Worker. Cela permet au fil principal de rester réactif, car les calculs intensifs sont effectués dans un fil séparé. Les utilisateurs peuvent continuer à interagir avec l'application pendant que le Web Worker gère le travail intensif en arrière-plan.

Les Web Workers sont également utiles pour effectuer des tâches en arrière-plan qui ne nécessitent pas d'interaction immédiate avec l'utilisateur.

Conseil: Préchargement de données avec les Web Workers

// Fil principal
const worker = new Worker('worker.js');
worker.onmessage = function(event) {
    console.log('Données chargées:', event.data);
};
worker.postMessage('start');
// worker.js
self.onmessage = function(event) {
    if (event.data === 'start') {
        // Précharger les données ou effectuer une tâche en arrière-plan
        self.postMessage('données chargées');
    }
};

En exécutant ces tâches dans un Web Worker, vous pouvez vous assurer qu'elles n'interfèrent pas avec la réactivité du fil principal. Le Web Worker peut travailler en arrière-plan, récupérer des données ou effectuer des mises à jour, sans impacter l'expérience utilisateur.

Un autre scénario où les Web Workers excellent est la gestion des scripts de longue durée.

Conseil: Gestion des scripts de longue durée avec les Web Workers

// Fil principal
const worker = new Worker('longTaskWorker.js');
worker.onmessage = function(event) {
    console.log('Tâche terminée:', event.data);
};
worker.postMessage('start');
// longTaskWorker.js
self.onmessage = function(event) {
    if (event.data === 'start') {
        // Effectuer une tâche de longue durée
        let result = effectuerCalculComplexe();
        self.postMessage(result);
    }
};

function effectuerCalculComplexe() {
    // Logique de calcul complexe
    return 'résultat calculé';
}

Si vous avez un script qui prend un temps considérable à s'exécuter, comme une tâche de traitement de données complexe ou une animation de longue durée, son exécution sur le fil principal peut figer l'interface utilisateur. En déplaçant le script de longue durée vers un Web Worker, vous pouvez garder le fil principal libre pour répondre aux interactions de l'utilisateur. Le Web Worker peut exécuter le script de manière asynchrone, permettant à l'application de rester réactive.

Limitations des Web Workers

Bien que les Web Workers offrent des avantages, ils ont aussi des limitations. Il est important d'être conscient de ces limitations lorsque vous décidez si les Web Workers conviennent à votre application.

Limitation Description
Pas d'accès au DOM Les Web Workers n'ont pas accès au Document Object Model (DOM). Un Web Worker ne peut pas manipuler ou mettre à jour directement les éléments de la page web. Si un Web Worker doit mettre à jour l'interface utilisateur, il doit envoyer un message au fil principal, qui peut ensuite mettre à jour le DOM.
Pas d'accès à l'objet Window Les Web Workers n'ont pas accès à l'objet window. L'objet window donne accès aux fonctionnalités et API spécifiques au navigateur, comme alert(), prompt(), ou location. Les Web Workers s'exécutent dans une portée globale séparée et ne peuvent pas interagir directement avec l'objet window.
Fonctionnalités JavaScript limitées Les Web Workers ont un accès limité à certaines fonctionnalités JavaScript. Par exemple, les Web Workers ne peuvent pas accéder à l'objet document, à l'objet parent, ou à l'objet console. Ils ont également un accès restreint à certaines API du navigateur, comme l'objet XMLHttpRequest ou l'objet localStorage.

Malgré ces limitations, les Web Workers restent un outil pour optimiser les performances des applications web. En concevant soigneusement l'architecture de votre application et son modèle de communication, vous pouvez tirer parti des Web Workers pour décharger les tâches intensives, effectuer du travail en arrière-plan et gérer les scripts de longue durée.

Communication avec les Web Workers

La communication avec les Web Workers implique l'envoi de messages entre le script principal et le Web Worker, ainsi que la réception de messages du Web Worker vers le script principal. La communication se fait par le biais de la méthode postMessage() et du gestionnaire d'événements onmessage.

Pour envoyer un message à un Web Worker, vous utilisez la méthode postMessage() depuis le script principal. La méthode postMessage() prend le message comme argument, qui peut être une valeur simple ou un objet.

Conseil: Envoi d'un message à un Web Worker

// Script principal
const worker = new Worker('worker.js');
worker.postMessage('Bonjour du script principal');

Du côté du Web Worker, vous pouvez recevoir le message en configurant un gestionnaire d'événements onmessage. L'objet événement passé au gestionnaire contient les données du message dans sa propriété data.

Conseil: Réception d'un message dans le Web Worker

// worker.js
self.onmessage = function(event) {
    console.log('Message reçu:', event.data);
};

De même, le Web Worker peut envoyer des messages au script principal en utilisant la méthode postMessage(). Le script principal peut recevoir ces messages en configurant son propre gestionnaire d'événements onmessage.

Conseil: Envoi de messages depuis le Web Worker et réception dans le script principal

// worker.js
self.postMessage('Bonjour du Web Worker');

// Script principal
worker.onmessage = function(event) {
    console.log('Message reçu du worker:', event.data);
};

En plus d'envoyer des valeurs ou des objets simples, vous pouvez également transférer des données en utilisant des objets transférables. Les objets transférables vous permettent de passer de grandes quantités de données, telles que ArrayBuffer ou MessagePort, entre le script principal et le Web Worker sans copier les données. Cela peut aider à améliorer les performances lors du traitement de grands ensembles de données. Pour transférer des données, vous passez un tableau d'objets transférables comme deuxième argument à la méthode postMessage().

Conseil: Transfert de grandes données avec des objets transférables

// Script principal
const largeData = new ArrayBuffer(1024 * 1024); // Données de 1 Mo
worker.postMessage({ data: largeData }, [largeData]);

Événement Message

L'événement message est l'événement clé pour gérer la communication entre le script principal et le Web Worker. Comprendre le fonctionnement de l'événement message est important pour envoyer et recevoir correctement les messages.

Lorsqu'un message est envoyé à l'aide de la méthode postMessage(), un événement message est déclenché du côté récepteur. L'objet événement contient les propriétés suivantes :

Propriété Description
data Les données du message envoyées par l'expéditeur.
origin L'origine de la fenêtre de l'expéditeur (script principal).
source Une référence à l'objet Worker de l'expéditeur (script principal) ou MessagePort (Web Worker).

Dans le script principal, vous pouvez gérer les messages du Web Worker en configurant un gestionnaire d'événements onmessage sur l'objet Worker. L'objet événement passé au gestionnaire contiendra les données du message dans sa propriété data.

Conseil: Gestion des messages du Web Worker dans le script principal

// Script principal
worker.onmessage = function(event) {
    console.log('Message reçu du worker:', event.data);
    // Traiter le message et effectuer des actions
};

De même, dans le script du Web Worker, vous pouvez gérer les messages du script principal en configurant un gestionnaire d'événements onmessage sur l'objet global self. L'objet événement passé au gestionnaire contiendra les données du message dans sa propriété data.

Conseil: Gestion des messages du script principal dans le Web Worker

// worker.js
self.onmessage = function(event) {
    console.log('Message reçu:', event.data);
    // Traiter le message et effectuer des actions
    self.postMessage('Message traité');
};

Gestion des erreurs des Web Workers

La gestion des erreurs est un aspect important du travail avec les Web Workers. Elle implique la gestion des erreurs qui peuvent survenir dans le script du Web Worker et l'envoi de ces erreurs au script principal pour action.

Pour gérer les erreurs dans les Web Workers, vous devez écouter les événements d'erreur. Le script du Web Worker peut déclencher un événement d'erreur en utilisant le gestionnaire d'événements self.onerror. Ce gestionnaire d'événements est appelé lorsqu'une erreur se produit dans le script du Web Worker.

Conseil: Gestion des erreurs dans un Web Worker

// worker.js
self.onerror = function(event) {
    console.error('Erreur dans le Web Worker:', event.message);
    // Gérer l'erreur ou effectuer des tâches de nettoyage
    self.postMessage({ error: event.message });
};

Dans l'exemple ci-dessus, le gestionnaire d'événements self.onerror est utilisé pour capturer toutes les erreurs qui se produisent dans le script du Web Worker. Vous pouvez enregistrer le message d'erreur, gérer l'erreur ou effectuer les tâches de nettoyage nécessaires.

Pour envoyer l'erreur au script principal, vous pouvez envoyer un message d'erreur en utilisant self.postMessage(). Le script principal peut alors écouter ce message d'erreur et prendre les mesures appropriées.

Conseil: Gestion des erreurs dans le script principal

// Script principal
worker.onmessage = function(event) {
    if (event.data.error) {
        console.error('Erreur reçue du Web Worker:', event.data.error);
        // Gérer l'erreur dans le script principal
    }
};

Dans le script principal, vous pouvez vérifier si le message reçu contient une propriété d'erreur. Si une erreur est reçue, vous pouvez enregistrer le message d'erreur et le gérer.

Erreurs courantes des Web Workers

Il existe quelques erreurs courantes que vous pouvez rencontrer lors du travail avec les Web Workers :

Erreur Description
Script introuvable Cette erreur se produit lorsque le fichier de script du Web Worker est introuvable ou ne peut pas être chargé. Assurez-vous que le chemin du fichier de script est correct et accessible.
Script invalide Cette erreur se produit lorsque le script du Web Worker contient une syntaxe JavaScript invalide ou n'est pas un fichier de script valide. Vérifiez le script pour détecter d'éventuelles erreurs de syntaxe.
Limite de mémoire dépassée Les Web Workers ont une limite de mémoire définie par le navigateur. Si le script du Web Worker utilise trop de mémoire, il peut générer une erreur "limite de mémoire dépassée". Assurez-vous que votre script gère efficacement les grands ensembles de données et évitez les fuites de mémoire.

Conseil: Erreur de script inexistant

// Script principal
const worker = new Worker('script-inexistant.js'); // Génère une erreur

Conseil: Erreur de syntaxe courante dans un Web Worker

// worker.js
console.log('Bonjour depuis le Web Worker') // Point-virgule manquant

Conseil: Limite de mémoire dépassée dans un Web Worker

// worker.js
const donneesVolumineuses = new Array(1000000000); // Allocation d'un grand tableau

En gérant les erreurs dans les Web Workers et en écoutant les événements d'erreur, vous pouvez gérer et récupérer les erreurs, offrant une meilleure expérience utilisateur et maintenant la stabilité de votre application web.

N'oubliez pas de tester soigneusement vos scripts de Web Worker et de gérer les erreurs à la fois dans le script du Web Worker et dans le script principal. Une bonne gestion des erreurs garantit que votre application peut gérer les situations imprévues et fournir des retours utiles à l'utilisateur lorsque nécessaire.

Techniques avancées pour les Web Workers

Les Web Workers offrent des techniques avancées qui vous permettent d'étendre leur fonctionnalité et de les utiliser avec d'autres fonctionnalités et API JavaScript. Examinons certaines de ces techniques avancées.

L'importation de scripts dans les Web Workers est un moyen de modulariser et de réutiliser du code au sein d'un Web Worker. En utilisant la fonction importScripts(), vous pouvez charger des fichiers JavaScript externes dans la portée du Web Worker. Cela vous permet de diviser votre code de worker en fichiers séparés pour une meilleure organisation et maintenabilité.

Conseil: Importation de scripts dans les Web Workers

// worker.js
importScripts('utility.js', 'math.js');

self.onmessage = function(event) {
    // Utiliser des fonctions ou des variables des scripts importés
    const result = performCalculation(event.data);
    self.postMessage(result);
};

L'utilisation des Web Workers avec des promesses est une autre technique puissante. Les promesses offrent un moyen de gérer les opérations asynchrones et d'améliorer la lisibilité du code. En enveloppant la communication entre le script principal et le Web Worker dans des promesses, vous pouvez créer un flux de données plus structuré et intuitif.

Conseil: Utilisation des Web Workers avec des promesses

// Script principal
function performTask(data) {
    return new Promise((resolve, reject) => {
        const worker = new Worker('worker.js');
        worker.onmessage = function(event) {
            resolve(event.data);
        };
        worker.onerror = function(error) {
            reject(error);
        };
        worker.postMessage(data);
    });
}

// Utilisation
performTask('Données de la tâche')
    .then(result => {
        console.log('Résultat de la tâche:', result);
    })
    .catch(error => {
        console.error('Erreur de la tâche:', error);
    });

Combiner les Web Workers avec d'autres API ouvre de nouvelles possibilités. Par exemple, vous pouvez utiliser les Web Workers avec l'API File pour effectuer des tâches de traitement de fichiers en arrière-plan. Cela vous permet de lire et de modifier des fichiers sans bloquer le thread principal.

Conseil: Combinaison des Web Workers avec l'API File

// Script principal
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(event) {
    const file = event.target.files[0];
    const worker = new Worker('fileWorker.js');
    worker.onmessage = function(event) {
        console.log('Fichier traité:', event.data);
    };
    worker.postMessage(file);
});

// fileWorker.js
self.onmessage = function(event) {
    const file = event.data;
    // Traiter le fichier dans le Web Worker
    // ...
    self.postMessage('Traitement du fichier terminé');
};

Bonnes pratiques pour les Web Workers

Lors de l'utilisation des Web Workers, il est important de suivre les bonnes pratiques pour en tirer le meilleur parti et éviter les pièges courants. Voici quelques points clés à prendre en compte :

Considération Description
Quand utiliser les Web Workers - Utilisez les Web Workers pour les tâches gourmandes en CPU qui peuvent être exécutées en arrière-plan.
- Évitez d'utiliser les Web Workers pour les tâches nécessitant une communication fréquente avec le thread principal.
- Tenez compte de la surcharge liée à la création et à la gestion des Web Workers pour les tâches petites ou de courte durée.
Performance - Soyez attentif à la quantité de données transférées entre le thread principal et les Web Workers.
- Utilisez des objets transférables (ArrayBuffer, MessagePort) pour éviter de copier de grandes quantités de données entre les threads.
- Minimisez la fréquence des échanges de messages pour réduire la surcharge de communication.
Sécurité - Assurez-vous que les scripts des Web Workers sont servis depuis la même origine que le script principal pour éviter les problèmes de sécurité liés aux origines croisées.
- Soyez prudent lorsque vous utilisez importScripts() pour charger des scripts externes, car ils peuvent introduire des vulnérabilités de sécurité.
- Validez et nettoyez toutes les données reçues des Web Workers pour prévenir les attaques par injection.

Voici la traduction en français :

Exemples de Web Workers

Les Web Workers offrent un moyen de déplacer des tâches du thread principal et d'améliorer les performances des applications web. Examinons quelques exemples qui montrent l'utilisation des Web Workers dans différentes situations.

Conseil: Exemple simple de Web Worker

// Script principal (main.js)
const worker = new Worker('worker.js');
worker.onmessage = function(event) {
  console.log('Résultat reçu du worker :', event.data);
};
worker.postMessage(5);

// Script du worker (worker.js)
self.onmessage = function(event) {
  const number = event.data;
  const result = fibonacci(number);
  self.postMessage(result);
};

function fibonacci(n) {
  if (n <= 1) {
    return n;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

Dans cet exemple simple, le script principal crée un nouveau Web Worker et lui envoie un nombre en utilisant postMessage(). Le script du worker reçoit le message, calcule le nombre de Fibonacci en utilisant une fonction récursive, et renvoie le résultat au script principal en utilisant postMessage(). Le script principal affiche le résultat reçu dans la console.

Conseil: Exemple complexe de Web Worker

// Script principal (main.js)
const worker = new Worker('worker.js');
worker.onmessage = function(event) {
  const { type, data } = event.data;
  if (type === 'progress') {
    updateProgressBar(data.progress);
  } else if (type === 'result') {
    displayResult(data.result);
  }
};
worker.postMessage({ type: 'start', data: { /* données complexes */ } });

// Script du worker (worker.js)
self.onmessage = function(event) {
  const { type, data } = event.data;
  if (type === 'start') {
    processData(data);
  }
};

function processData(data) {
  // Effectuer un traitement de données complexe
  for (let i = 0; i < data.length; i++) {
    // Traiter l'élément de données
    const progress = ((i + 1) / data.length) * 100;
    self.postMessage({ type: 'progress', data: { progress } });
  }
  const result = { /* données traitées */ };
  self.postMessage({ type: 'result', data: { result } });
}

Dans cet exemple plus complexe, le script principal envoie un message au worker avec un type et des données spécifiques. Le script du worker reçoit le message, vérifie le type du message et effectue l'action appropriée. Dans ce cas, lorsque le type de message est 'start', le worker traite les données reçues. Pendant le traitement, le worker envoie des mises à jour de progression au script principal en utilisant postMessage(). Une fois le traitement terminé, le worker envoie le résultat final au script principal. Le script principal gère les messages reçus en fonction de leur type, en mettant à jour la barre de progression ou en affichant le résultat.

Cas d'utilisation réels pour les Web Workers

Cas d'utilisation Description
Traitement de données en arrière-plan Les Web Workers peuvent être utilisés pour traiter de grands ensembles de données ou effectuer des calculs complexes en arrière-plan sans affecter la réactivité du thread principal. Cela est utile pour les applications qui traitent l'analyse de données, le traitement d'images ou les simulations scientifiques.
Requêtes API asynchrones Les Web Workers peuvent être utilisés pour effectuer des requêtes API asynchrones et gérer les réponses sans bloquer le thread principal. Cela améliore la performance perçue des applications web en permettant à l'interface utilisateur de rester réactive pendant l'attente des réponses API.
Mises à jour en temps réel Les Web Workers peuvent être utilisés pour implémenter des mises à jour en temps réel dans les applications web. Par exemple, un Web Worker peut être responsable de la réception des mises à jour d'un serveur via WebSocket ou long-polling et de la notification du thread principal pour mettre à jour l'interface utilisateur. Cela laisse le thread principal libre pour gérer les interactions de l'utilisateur.
Prétraitement des données pour la visualisation Les Web Workers peuvent être utilisés pour prétraiter de grands ensembles de données avant de les visualiser sur le thread principal. Cela peut impliquer le filtrage, l'agrégation ou la transformation des données pour réduire la charge de travail sur le thread principal et améliorer les performances de rendu des graphiques ou des diagrammes.

Ce ne sont que quelques exemples de la façon dont les Web Workers peuvent être utilisés dans des scénarios réels. La flexibilité et la puissance des Web Workers les rendent précieux pour déplacer des tâches, effectuer des traitements en arrière-plan et améliorer les performances globales des applications web.