Catégories
Astuces et Design

Gérer des tâches de longue durée dans une application React avec des Web Workers – Smashing Magazine

A propos de l'auteur

Développeur frontend génial qui aime tout le codage. Je suis un amoureux de la musique chorale et je travaille pour la rendre plus accessible au monde, une mise en ligne à un…
Plus à propos
Chidi

Dans ce didacticiel, nous allons apprendre à utiliser l'API Web Worker pour gérer les tâches chronophages et de blocage d'interface utilisateur dans une application JavaScript en créant un exemple d'application Web qui exploite les Web Workers. Enfin, nous terminerons l'article en transférant le tout dans une application React.

Le temps de réponse est un gros problème pour les applications Web. Les utilisateurs exigent des réponses instantanées, peu importe ce que fait votre application. Qu'il s'agisse d'afficher uniquement le nom d'une personne ou de calculer les chiffres, les utilisateurs d'applications Web exigent que votre application réponde à leur commande à chaque fois. Parfois, cela peut être difficile à réaliser étant donné la nature mono-thread de JavaScript. Mais dans cet article, nous allons découvrir comment nous pouvons tirer parti de l'API Web Worker pour offrir une meilleure expérience.

En écrivant cet article, j'ai fait les hypothèses suivantes:

  1. Pour pouvoir suivre, vous devez avoir au moins une certaine familiarité avec JavaScript et l'API de document;
  2. Vous devez également avoir une connaissance pratique de React afin de pouvoir démarrer avec succès un nouveau projet React à l'aide de Create React App.

Si vous avez besoin de plus d'informations sur ce sujet, j'ai inclus un certain nombre de liens dans la section "Autres ressources" pour vous aider à vous mettre à jour.

Tout d'abord, commençons avec les Web Workers.

Qu'est-ce qu'un Web Worker?

Pour comprendre les Web Workers et le problème qu'ils sont censés résoudre, il est nécessaire de comprendre comment le code JavaScript est exécuté lors de l'exécution. Pendant l'exécution, le code JavaScript est exécuté de manière séquentielle et étape par étape. Une fois qu'un morceau de code se termine, le suivant en ligne commence à s'exécuter, et ainsi de suite. En termes techniques, nous disons que JavaScript est mono-thread. Ce comportement implique qu'une fois qu'un morceau de code commence à s'exécuter, chaque code qui suit doit attendre que ce code termine son exécution. Ainsi, chaque ligne de code «bloque» l'exécution de tout ce qui vient après. Il est donc souhaitable que chaque morceau de code se termine le plus rapidement possible. Si un morceau de code prend trop de temps à se terminer, notre programme semble avoir cessé de fonctionner. Sur le navigateur, cela se manifeste par une page figée et qui ne répond pas. Dans certains cas extrêmes, l'onglet se fige complètement.

Imaginez conduire sur une seule voie. Si l'un des conducteurs devant vous arrête de bouger pour une raison quelconque, vous avez un embouteillage. Avec un programme comme Java, le trafic pourrait se poursuivre sur d'autres voies. Ainsi Java est dit multi-thread. Les Web Workers tentent d'apporter comportement multi-thread à JavaScript.

La capture d'écran ci-dessous montre que l'API Web Worker est prise en charge par de nombreux navigateurs, vous devez donc vous sentir en confiance pour l'utiliser.

Affichage du graphique de prise en charge du navigateur pour les web workers
Prise en charge du navigateur Web Workers. (Grand aperçu)

Les Web Workers s'exécutent dans des threads d'arrière-plan sans interférer avec l'interface utilisateur, et ils communiquent avec le code qui les a créés via des gestionnaires d'événements.

Une excellente définition d'un Web Worker vient de MDN:

«Un worker est un objet créé à l'aide d'un constructeur (par ex. Worker() qui exécute un fichier JavaScript nommé – ce fichier contient le code qui s'exécutera dans le thread de travail; les travailleurs s'exécutent dans un autre contexte global différent de l'actuel window. Ainsi, en utilisant le window raccourci pour obtenir la portée globale actuelle (au lieu de self dans un Worker renverra une erreur. »

Un travailleur est créé à l'aide du Worker constructeur.

const worker = new Worker('worker-file.js')

Il est possible d'exécuter la plupart du code dans un web worker, à quelques exceptions près. Par exemple, vous ne pouvez pas manipuler le DOM depuis l'intérieur d'un worker. Il n'y a pas d'accès au document API.

Les travailleurs et le fil qui les engendre s'envoient des messages en utilisant le postMessage() méthode. De même, ils répondent aux messages en utilisant le onmessage gestionnaire d'événements. Il est important de comprendre cette différence. L'envoi de messages est réalisé à l'aide d'une méthode; la réception d'un message nécessite un gestionnaire d'événements. Le message reçu est contenu dans le data attribut de l'événement. Nous en verrons un exemple dans la section suivante. Mais permettez-moi de mentionner rapidement que le type de travailleur dont nous avons parlé s’appelle un «travailleur dévoué». Cela signifie que le worker n'est accessible qu'au script qui l'a appelé. Il est également possible d'avoir un worker accessible à partir de plusieurs scripts. Ceux-ci sont appelés travailleurs partagés et sont créés à l'aide du SharedWorker constructeur, comme indiqué ci-dessous.

const sWorker = new SharedWorker('shared-worker-file.js')

Pour en savoir plus sur les travailleurs, veuillez consulter cet article MDN. Le but de cet article est de vous familiariser avec l'utilisation des agents Web. Allons-y en calculant le nième nombre de Fibonacci.

Calcul du nième nombre de Fibonacci

Remarque: Pour cette section et les deux suivantes, j'utilise Live Server sur VSCode pour exécuter l'application. Vous pouvez certainement utiliser autre chose.

C'est la section que vous attendiez. Nous allons enfin écrire du code pour voir les Web Workers en action. Eh bien, pas si vite. Nous n’apprécierions pas le travail accompli par un Web Worker à moins que nous ne soyons confrontés au genre de problèmes qu’il résout. Dans cette section, nous allons voir un exemple de problème, et dans la section suivante, nous verrons comment un collaborateur Web nous aide à faire mieux.

Imaginez que vous construisiez une application Web permettant aux utilisateurs de calculer le nième numéro de Fibonacci. Si vous ne connaissez pas le terme «nombre de Fibonacci», vous pouvez en savoir plus ici, mais en résumé, les nombres de Fibonacci sont une séquence de nombres telle que chaque nombre est la somme des deux nombres précédents.

Mathématiquement, il s'exprime comme suit:

Ainsi, les premiers nombres de la séquence sont:

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ...

Dans certaines sources, la séquence commence à F0 = 0, auquel cas la formule ci-dessous vaut pour n > 1:

Dans cet article, nous commencerons par F1 = 1. Une chose que nous pouvons voir tout de suite à partir de la formule est que les nombres suivent un modèle récursif. La tâche à accomplir maintenant est d'écrire une fonction récursive pour calculer le nième nombre de Fibonacci (FN).

Après quelques essais, je pense que vous pouvez facilement trouver la fonction ci-dessous.

const fib = n => {
  if (n < 2) {
    return n // or 1
  } else {
    return fib(n - 1) + fib(n - 2)
  }
}

La fonction est simple. Si n est inférieur à 2, renvoie n (ou 1), sinon, renvoie la somme des n-1 et n-2 FNs. Avec les fonctions fléchées et l'opérateur ternaire, nous pouvons créer un one-liner.

const fib = n => (n < 2 ? n : fib(n-1) + fib(n-2))

Cette fonction a une complexité temporelle de 0(2n). Cela signifie simplement que lorsque la valeur de n augmente, le temps nécessaire pour calculer la somme augmente de façon exponentielle. Cela en fait une tâche très longue qui pourrait potentiellement interférer avec notre interface utilisateur, pour de grandes valeurs de n. Voyons cela en action.

Remarque: Ce n'est en aucun cas la meilleure façon de résoudre ce problème particulier. Mon choix d'utiliser cette méthode est pour les besoins de cet article.

Pour commencer, créez un nouveau dossier et nommez-le comme vous le souhaitez. Maintenant, dans ce dossier, créez un src/ dossier. Créez également un index.html fichier dans le dossier racine. À l'intérieur de src/ dossier, créez un fichier nommé index.js.

S'ouvrir index.html et ajoutez le code HTML suivant.




  


  

Calcul du nième nombre de Fibonnaci

Cette partie est très simple. Premièrement, nous avons un titre. Ensuite, nous avons un conteneur avec une entrée et un bouton. Un utilisateur saisit un nombre puis clique sur «Calculer». Nous avons également un conteneur pour contenir le résultat du calcul. Enfin, nous incluons le src/index.js fichier dans un script marque.

Vous pouvez supprimer le lien de la feuille de style. Mais si vous manquez de temps, j'ai défini des CSS que vous pouvez utiliser. Créez simplement le styles.css fichier dans le dossier racine et ajoutez les styles ci-dessous:


body {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  
  .body-container,
  .heading-container {
    padding: 0 20px;
  }
  
  .heading-container {
    padding: 20px;
    color: white;
    background: #7a84dd;
  }
  
  .heading-container > h1 {
    margin: 0;
  }
  
  .body-container {
    width: 50%
  }
  
  .input-div {
    margin-top: 15px;
    margin-bottom: 15px;
    display: flex;
    align-items: center;
  }
  
  .results {
    width: 50vw;
  }
  
  .results>p {
    font-size: 24px;
  }
  
  .result-div {
    padding: 5px 10px;
    border-radius: 5px;
    margin: 10px 0;
    background-color: #e09bb7;
  }
  
  .result-div p {
    margin: 5px;
  }
  
  span.bold {
    font-weight: bold;
  }
  
  input {
    font-size: 25px;
  }
  
  p.error {
    color: red;
  }
  
  .number-input {
    padding: 7.5px 10px;
  }
  
  .btn-submit {
    padding: 10px;
    border-radius: 5px;
    border: none;
    background: #07f;
    font-size: 24px;
    color: white;
    cursor: pointer;
    margin: 0 10px;
  }

Maintenant ouvre src/index.js développons-le lentement. Ajoutez le code ci-dessous.

const fib = (n) => (n < 2 ? n : fib(n - 1) + fib(n - 2));

const ordinal_suffix = (num) => {
  // 1st, 2nd, 3rd, 4th, etc.
  const j = num % 10;
  const k = num % 100;
  switch (true) {
    case j === 1 && k !== 11:
      return num + "st";
    case j === 2 && k !== 12:
      return num + "nd";
    case j === 3 && k !== 13:
      return num + "rd";
    default:
      return num + "th";
  }
};
const textCont = (n, fibNum, time) => {
  const nth = ordinal_suffix(n);
  return `
  

Time: ${time} ms

${nth} fibonnaci number: ${fibNum}

`; };

Ici, nous avons trois fonctions. La première est la fonction que nous avons vue précédemment pour calculer le nième FN. La deuxième fonction est simplement une fonction utilitaire pour attacher un suffixe approprié à un nombre entier. La troisième fonction prend quelques arguments et produit un balisage que nous insérerons plus tard dans le DOM. Le premier argument est le nombre dont FN est en cours de calcul. Le deuxième argument est le FN calculé. Le dernier argument est le temps nécessaire pour effectuer le calcul.

Toujours dedans src/index.js, ajoutez le code ci-dessous juste sous le précédent.

const errPar = document.getElementById("error");
const btn = document.getElementById("submit-btn");
const input = document.getElementById("number-input");
const resultsContainer = document.getElementById("results-container");

btn.addEventListener("click", (e) => {
  errPar.textContent = '';
  const num = window.Number(input.value);

  if (num < 2) {
    errPar.textContent = "Please enter a number greater than 2";
    return;
  }

  const startTime = new Date().getTime();
  const sum = fib(num);
  const time = new Date().getTime() - startTime;

  const resultDiv = document.createElement("div");
  resultDiv.innerHTML = textCont(num, sum, time);
  resultDiv.className = "result-div";
  resultsContainer.appendChild(resultDiv);
});

Tout d'abord, nous utilisons le document API à prendre en main DOM nœuds dans notre fichier HTML. Nous obtenons une référence au paragraphe où nous afficherons les messages d'erreur; l'entrée; le bouton de calcul et le conteneur dans lequel nous afficherons nos résultats.

Ensuite, nous attachons un gestionnaire d'événement «clic» au bouton. Lorsque le bouton est cliqué, nous prenons tout ce qui se trouve à l'intérieur de l'élément d'entrée et le convertissons en un nombre, si nous obtenons quelque chose de moins de 2, nous affichons un message d'erreur et retournons. Si nous obtenons un nombre supérieur à 2, nous continuons. Tout d'abord, nous enregistrons l'heure actuelle. Après cela, nous calculons le FN. Lorsque cela se termine, nous obtenons un décalage horaire qui représente la durée du calcul. Dans la partie restante du code, nous créons un nouveau div. Nous définissons ensuite son code HTML interne comme la sortie du textCont() fonction que nous avons définie précédemment. Enfin, nous lui ajoutons une classe (pour le style) et l'ajoutons au conteneur de résultats. L'effet de ceci est que chaque calcul apparaîtra dans un div sous le précédent.

Affichage des nombres de Fibonacci calculés jusqu'à 43
Quelques numéros de Fibonacci. (Grand aperçu)

Nous pouvons voir que lorsque le nombre augmente, le temps de calcul augmente également (de manière exponentielle). Par exemple, de 30 à 35, nous avons fait passer le temps de calcul de 13 ms à 130 ms. On peut encore considérer ces opérations comme «rapides». À 40, nous voyons un temps de calcul supérieur à 1 seconde. Sur ma machine, c'est là que je commence à remarquer que la page ne répond plus. À ce stade, je ne peux plus interagir avec la page pendant que le calcul est en cours. Je ne peux pas me concentrer sur l’entrée ou faire autre chose.

Rappelez-vous quand nous avons parlé de JavaScript étant monothread? Eh bien, ce thread a été «bloqué» par ce calcul de longue durée, donc tout le reste doit «attendre» qu'il se termine. Il peut commencer à une valeur inférieure ou supérieure sur votre ordinateur, mais vous êtes obligé d'atteindre ce point. Notez qu'il a fallu près de 10 secondes pour calculer celle de 44. S'il y avait d'autres choses à faire sur votre application Web, eh bien, l'utilisateur doit attendre que Fib (44) se termine avant de pouvoir continuer. Mais si vous avez déployé un travailleur Web pour gérer ce calcul, vos utilisateurs pourraient continuer avec autre chose pendant l'exécution.

Voyons maintenant comment les professionnels du Web nous aident à surmonter ce problème.

Un exemple de Web Worker en action

Dans cette section, nous allons déléguer le travail de calcul du nième FN à un travailleur Web. Cela aidera à libérer le fil principal et à garder notre interface utilisateur réactive pendant que le calcul est en cours.

Démarrer avec les web workers est étonnamment simple. Voyons comment. Créer un nouveau fichier src/fib-worker.js. et entrez le code suivant.

const fib = (n) => (n < 2 ? n : fib(n - 1) + fib(n - 2));

onmessage = (e) => {
  const { num } = e.data;
  const startTime = new Date().getTime();
  const fibNum = fib(num);
  postMessage({
    fibNum,
    time: new Date().getTime() - startTime,
  });
};

Notez que nous avons déplacé la fonction qui calcule le nième nombre de Fibonacci, fib dans ce fichier. Ce fichier sera exécuté par notre web worker.

Rappel dans la section Qu'est-ce qu'un web worker, nous avons mentionné que les web workers et leurs parents communiquent en utilisant le onmessage gestionnaire d'événements et postMessage() méthode. Ici, nous utilisons le onmessage gestionnaire d'événements pour écouter les messages du script parent. Une fois que nous recevons un message, nous déstructurons le numéro de l'attribut data de l'événement. Ensuite, nous obtenons l'heure actuelle et commençons le calcul. Une fois le résultat prêt, nous utilisons le postMessage() méthode pour publier les résultats dans le script parent.

S'ouvrir src/index.js faisons quelques changements.

...

const worker = new window.Worker("src/fib-worker.js");

btn.addEventListener("click", (e) => {
  errPar.textContent = "";
  const num = window.Number(input.value);
  if (num < 2) {
    errPar.textContent = "Please enter a number greater than 2";
    return;
  }

  worker.postMessage({ num });
  worker.onerror = (err) => err;
  worker.onmessage = (e) => {
    const { time, fibNum } = e.data;
    const resultDiv = document.createElement("div");
    resultDiv.innerHTML = textCont(num, fibNum, time);
    resultDiv.className = "result-div";
    resultsContainer.appendChild(resultDiv);
  };
});

La première chose à faire est de créer le web worker à l'aide du Worker constructeur. Ensuite, dans l'écouteur d'événements de notre bouton, nous envoyons un numéro au collaborateur en utilisant worker.postMessage({ num }). Après cela, nous définissons une fonction pour écouter les erreurs dans le worker. Ici, nous renvoyons simplement l'erreur. Vous pouvez certainement faire plus si vous le souhaitez, comme l'afficher dans DOM. Ensuite, nous écoutons les messages du travailleur. Une fois qu'on reçoit un message, on déstructure time et fibNum, et continuez le processus de les afficher dans le DOM.

Notez qu'à l'intérieur du web worker, le onmessage l'événement est disponible dans la portée du collaborateur, nous aurions donc pu l'écrire sous la forme self.onmessage et self.postMessage(). Mais dans le script parent, nous devons les attacher au travailleur lui-même.

Dans la capture d'écran ci-dessous, vous verrez le fichier de travail Web dans l'onglet sources des outils de développement Chrome. Ce que vous devez noter, c'est que l'interface utilisateur reste réactive quel que soit le numéro que vous entrez. Ce comportement est la magie des web workers.

Affichage d'un fichier de travail Web actif
Un fichier de travail Web en cours d'exécution. (Grand aperçu)

Nous avons beaucoup progressé avec notre application Web. Mais il y a autre chose que nous pouvons faire pour l’améliorer. Notre implémentation actuelle utilise un seul worker pour gérer chaque calcul. Si un nouveau message arrive alors que l'un d'eux est en cours d'exécution, l'ancien est remplacé. Pour contourner cela, nous pouvons créer un nouveau travailleur pour chaque appel afin de calculer le FN. Voyons comment procéder dans la section suivante.

Travailler avec plusieurs travailleurs Web

Actuellement, nous traitons chaque demande avec un seul collaborateur. Ainsi, une demande entrante remplacera une précédente qui n'est pas encore terminée. Ce que nous voulons maintenant, c'est apporter un petit changement pour générer un nouveau web worker pour chaque requête. Nous tuerons ce travailleur une fois que ce sera fait.

S'ouvrir src/index.js et déplacez la ligne qui crée le travailleur Web dans le gestionnaire d'événements de clic du bouton. Maintenant, le gestionnaire d'événements devrait ressembler à ci-dessous.

btn.addEventListener("click", (e) => {
  errPar.textContent = "";
  const num = window.Number(input.value);
  
  if (num < 2) {
    errPar.textContent = "Please enter a number greater than 2";
    return;
  }
  
  const worker = new window.Worker("src/fib-worker.js"); // this line has moved inside the event handler
  worker.postMessage({ num });
  worker.onerror = (err) => err;
  worker.onmessage = (e) => {
    const { time, fibNum } = e.data;
    const resultDiv = document.createElement("div");
    resultDiv.innerHTML = textCont(num, fibNum, time);
    resultDiv.className = "result-div";
    resultsContainer.appendChild(resultDiv);
    worker.terminate() // this line terminates the worker
  };
});

Nous avons fait deux changements.

  1. Nous avons déplacé cette ligne const worker = new window.Worker("src/fib-worker.js") dans le gestionnaire d’événements de clic du bouton.
  2. Nous avons ajouté cette ligne worker.terminate() pour supprimer le collaborateur une fois que nous en avons terminé.

Ainsi, pour chaque clic sur le bouton, nous créons un nouveau worker pour gérer le calcul. Ainsi, nous pouvons continuer à modifier l'entrée, et chaque résultat apparaîtra à l'écran une fois le calcul terminé. Dans la capture d'écran ci-dessous, vous pouvez voir que les valeurs de 20 et 30 apparaissent avant celle de 45. Mais j'ai commencé 45 en premier. Une fois que la fonction retourne pour 20 et 30, leurs résultats ont été affichés et le travailleur a été licencié. Lorsque tout est terminé, nous ne devrions pas avoir de nœuds de calcul dans l'onglet Sources.

montrant les nombres de Fibonacci avec les travailleurs licenciés
Illustration de plusieurs travailleurs indépendants. (Grand aperçu)

Nous pourrions terminer cet article ici, mais s'il s'agissait d'une application de réaction, comment y intégrerions-nous les travailleurs Web. C'est l'objet de la section suivante.

Travailleurs Web en réaction

Pour commencer, créez une nouvelle application de réaction à l'aide de l'ARC. Copiez le fib-worker.js fichier dans le public/ dossier de votre application de réaction. Mettre le fichier ici découle du fait que les applications React sont des applications d'une seule page. C’est à peu près la seule chose qui est spécifique à l’utilisation du nœud de calcul dans une application de réaction. Tout ce qui en découle est du pur React.

Dans src/ dossier créer un fichier helpers.js et exportez le ordinal_suffix() fonction de celui-ci.

// src/helpers.js

export const ordinal_suffix = (num) => {
  // 1st, 2nd, 3rd, 4th, etc.
  const j = num % 10;
  const k = num % 100;
  switch (true) {
    case j === 1 && k !== 11:
      return num + "st";
    case j === 2 && k !== 12:
      return num + "nd";
    case j === 3 && k !== 13:
      return num + "rd";
    default:
      return num + "th";
  }
};

Notre application nous obligera à conserver un état, alors créez un autre fichier, src/reducer.js et collez dans le réducteur d'état.

// src/reducers.js

export const reducer = (state = {}, action) => {
  switch (action.type) {
    case "SET_ERROR":
      return { ...state, err: action.err };
    case "SET_NUMBER":
      return { ...state, num: action.num };
    case "SET_FIBO":
      return {
        ...state,
        computedFibs: (
          ...state.computedFibs,
          { id: action.id, nth: action.nth, loading: action.loading },
        ),
      };
    case "UPDATE_FIBO": {
      const curr = state.computedFibs.filter((c) => c.id === action.id)(0);
      const idx = state.computedFibs.indexOf(curr);
      curr.loading = false;
      curr.time = action.time;
      curr.fibNum = action.fibNum;
      state.computedFibs(idx) = curr;
      return { ...state };
    }
    default:
      return state;
  }
};

Passons en revue chaque type d'action l'un après l'autre.

  1. SET_ERROR: définit un état d'erreur lors du déclenchement.
  2. SET_NUMBER: définit la valeur de notre zone de saisie sur state.
  3. SET_FIBO: ajoute une nouvelle entrée au tableau des FN calculés.
  4. UPDATE_FIBO: ici nous cherchons une entrée particulière et la remplaçons par un nouvel objet qui a le FN calculé et le temps de le calculer.

Nous utiliserons ce réducteur sous peu. Avant cela, créons le composant qui affichera les FN calculés. Créer un nouveau fichier src/Results.js et collez le code ci-dessous.

// src/Results.js

import React from "react";

export const Results = (props) => {
  const { results } = props;
  return (
    
{results.map((fb) => { const { id, nth, time, fibNum, loading } = fb; return (
{loading ? (

Calculating the{" "} {nth} {" "} Fibonacci number...

) : ( <>

Time: {time} ms

{nth} {" "} fibonnaci number:{" "} {fibNum}

)}
); })}
); };

Avec ce changement, nous commençons le processus de conversion de notre précédent fichier index.html en jsx. Ce fichier a une responsabilité: prendre un tableau d'objets représentant les FN calculés et les afficher. La seule différence par rapport à ce que nous avions auparavant est l'introduction d'un état de chargement. Alors maintenant, lorsque le calcul est en cours d'exécution, nous montrons l'état de chargement pour informer l'utilisateur que quelque chose se passe.

Ajoutons les derniers éléments en mettant à jour le code à l'intérieur src/App.js. Le code est assez long, nous allons donc le faire en deux étapes. Ajoutons le premier bloc de code.

import React from "react";
import "./App.css";
import { ordinal_suffix } from "./helpers";
import { reducer } from './reducer'
import { Results } from "./Results";
function App() {
  const (info, dispatch) = React.useReducer(reducer, {
    err: "",
    num: "",
    computedFibs: (),
  });
  const runWorker = (num, id) => {
    dispatch({ type: "SET_ERROR", err: "" });
    const worker = new window.Worker('./fib-worker.js')
    worker.postMessage({ num });
    worker.onerror = (err) => err;
    worker.onmessage = (e) => {
      const { time, fibNum } = e.data;
      dispatch({
        type: "UPDATE_FIBO",
        id,
        time,
        fibNum,
      });
      worker.terminate();
    };
  };
  return (
    

Computing the nth Fibonnaci number

{info.err}

// ... next block of code goes here ... //
); } export default App;

Comme d'habitude, nous apportons nos importations. Ensuite, nous instancions une fonction d'état et de mise à jour avec le hook useReducer. On définit alors une fonction, runWorker(), qui prend un nombre et un ID et définit l'appel d'un travailleur Web pour calculer le FN pour ce nombre.

Notez que pour créer le worker, nous transmettons un chemin relatif au constructeur du worker. Au moment de l'exécution, notre code React est attaché au public/index.html fichier, ainsi il peut trouver le fib-worker.js fichier dans le même répertoire. Lorsque le calcul est terminé (déclenché par worker.onmessage), le UPDATE_FIBO l'action est distribuée et le travailleur est arrêté par la suite. Ce que nous avons maintenant n'est pas très différent de ce que nous avions auparavant.

Dans le bloc de retour de ce composant, nous rendons le même HTML que nous avions auparavant. Nous passons également le tableau de nombres calculés au composant pour le rendu.

Ajoutons le dernier bloc de code dans le return déclaration.

        
dispatch({ type: "SET_NUMBER", num: window.Number(e.target.value), }) } />

Nous définissons un onChange handler sur l'entrée pour mettre à jour le info.num état variable. Sur le bouton, nous définissons un onClick gestionnaire d'événements. Lorsque le bouton est cliqué, nous vérifions si le nombre est supérieur à 2. Notez qu'avant d'appeler runWorker(), nous envoyons d'abord une action pour ajouter une entrée au tableau des FN calculés. C'est cette entrée qui sera mise à jour une fois que le travailleur aura terminé son travail. De cette façon, chaque entrée conserve sa position dans la liste, contrairement à ce que nous avions auparavant.

Enfin, copiez le contenu de styles.css d'avant et remplacer le contenu de App.css.

Nous avons maintenant tout en place. Maintenant, démarrez votre serveur de réaction et jouez avec quelques chiffres. Prenez note de l'état de chargement, qui est une amélioration UX. Notez également que l'interface utilisateur reste réactive même lorsque vous entrez un nombre aussi élevé que 1000 et cliquez sur «Calculer».

montrant l'état de chargement pendant que le travailleur est actif.
Affichage de l'état de chargement et du travailleur Web actif. (Grand aperçu)

Notez l'état de chargement et le travailleur actif. Une fois que la 46ème valeur est calculée, le travailleur est tué et l'état de chargement est remplacé par le résultat final.

Conclusion

Phew! Le trajet a été long, alors terminons-le. Je vous encourage à jeter un œil à l'entrée MDN pour les travailleurs Web (voir la liste des ressources ci-dessous) pour découvrir d'autres façons d'utiliser les travailleurs Web.

Dans cet article, nous avons découvert ce que sont les collaborateurs Web et le type de problèmes qu'ils sont censés résoudre. Nous avons également vu comment les implémenter en utilisant du JavaScript brut. Enfin, nous avons vu comment implémenter des web workers dans une application React.

Je vous encourage à profiter de cette excellente API pour offrir une meilleure expérience à vos utilisateurs.

Autres ressources

  • Console.time(), Documents Web MDN
  • {JSON} Espace réservé, site officiel
  • Utilisation de Web Workers, documents Web MDN
  • Numéro de Fibonacci, Wikipedia
  • Opérateur conditionnel (ternaire), documentation Web MDN
  • Document, API Web, documents Web MDN
  • Premiers pas, créer une application React (docs)
  • Function.prototype.toString(), Documents Web MDN
  • Documents Web IIFE, MDN
  • workerSetup.js, Super tutoriels Fullstack, GitHub
  • "Programmation parallèle en JavaScript à l'aide de Web Workers", Uday Hiwarale, Medium
Éditorial fracassant(ks, ra, yk, il)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *