Maison > Article > interface Web > Utilisation de Web Workers pour le traitement en arrière-plan dans les applications React Hooks.
Les Web Workers dans React sont des fonctions qui permettent l'exécution simultanée de plusieurs threads dans une application React. Ils permettent à certains threads de s'exécuter en arrière-plan, pour les exclure de l'exécution dans le cadre du thread principal.
Prenons par exemple une application dans laquelle vous souhaitez peut-être effectuer un calcul complexe, récupérer des données volumineuses à partir d'une API ou implémenter une notification en arrière-plan, sans altérer la fonctionnalité normale du thread principal en cours d'exécution. Ceci peut être réalisé en implémentant des React Web Hooks qui garantissent que l'interface utilisateur ne se fige pas pendant que tous ces processus s'exécutent dans une application React.
Dans ce guide, nous allons créer un exemple de projet de réaction qui implémente des Web Workers dans des hooks de réaction personnalisés pour effectuer un calcul exponentiel.
Créez une application de réaction.
npx create-vite myproject -- --template react
Je préfère utiliser vite pour créer une application de réaction car son temps d'exécution est plus rapide que create-react-app .
Ici, nous utilisons React comme modèle de vite.
sélectionnez JavaScript :
ouvrez le projet sur un éditeur. (J'utiliserai le code Vs pour ce projet)
code .
Dans le répertoire src, créez un autre répertoire hooks/useWebWorkers.
Dans ce dossier, créez un fichier index.js qui contiendra notre web worker comme indiqué ci-dessous :
Dans notre /hooks/useWebWorker/index.js, nous créons un hook personnalisé, qui crée notre web worker
Créez un hook personnalisé useWebWorker qui prend workerFunction et inputData comme paramètres.
const useWebWorker =(workerFunction,inputData)=>{ } export default useWebWorker;
Initialisez les états pour notre résultat, notre erreur et le statut de notre travailleur Web à l'aide du hook useState.
import {useState} from 'react' const useWebWorker =(workerFunction,inputData)=>{ const [result,setResult] = useState(null); const [error,setError] = useState(null); const [loading,setLoading] = useState(false); } export default useWebWorker;
i) result stocke le résultat de notre web worker. Initialement défini sur null.
ii)error garde une trace de l'erreur qui peut survenir dans le Web Worker. Initialement défini sur null.
iii) le chargement donne l'état de notre travailleur Web, qu'il traite ou non des données. Initialement défini sur false.
Initialisez un useEffect pour contenir notre web worker.
import {useState,useEffect} from 'react' const useWebWorker =(workerFunction,inputData)=>{ const [result,setResult] = useState(null); const [error,setError] = useState(null); const [loading,setLoading] = useState(false); useEffect(()=>{ },[inputData]) } export default useWebWorker;
Le hook useEffect s'exécute chaque fois que inputData change, car il a été défini comme délimiteur,
Lorsque le inputData est nul ou non défini, le hook se termine plus tôt.
if(!inputData)return;
Assurez-vous que tous les états sont correctement réinitialisés
setLoading(true); setError(null); setResult(null);
const blob = new Blob( [ ` self.onmessage = function(event) { (${workerFunction.toString()})(event); }; `, ], { type: "application/javascript" } );
Convertit WorkerFunction en chaîne et l'inclut dans un objet Blob. Ce Blob représente le code JavaScript qui s'exécutera dans Web Worker.
Créez un Worker qui génère une URL pour le Blob et crée un nouveau Web Worker en utilisant cette URL :
const workerScriptUrl = URL.createObjectURL(blob); const worker = new Worker(workerScriptUrl);
Configurez un gestionnaire d'événements pour le message émis par le travailleur.
worker.onmessage(event){ }
Lorsque le travailleur Web envoie un message au fil de discussion principal (en utilisant postMessage), le gestionnaire d'événements est déclenché.
event.data contient soit un résultat valide, soit une erreur dans le Web Worker. Nous gérons le rendu de l'erreur ou des résultats valides dans les instructions if-else.
En cas d'erreur, nous définissons l'erreur sur event.data.error dans setError().
si des résultats valides sont renvoyés, nous transmettons le résultat à event.data dans setResult()
worker.onmessage = (event) => { console.log("Worker result:", event.data); if (event.data.error) { setError(event.data.error); } else { setResult(event.data); } setLoading(false); };
Définit le chargement sur false une fois terminé.
Nous utilisons worker.onerror(event){
}
Nous passons l'événement en paramètre, mettons à jour l'erreur en event.message et mettons à jour l'état de chargement sur false.
worker.onerror = (event) => { console.error("Worker error:", event.message); setError(event.message); setLoading(false); };
Nous envoyons maintenant les inputData au web worker
worker.postMessage(inputData);
Nous mettons fin au Web Worker et révoquons l'URL du Blob lorsque le composant est démonté ou que inputData ou workerFunction change :
return () => { worker.terminate(); URL.revokeObjectURL(workerScriptUrl); }; }, [inputData, workerFunction]);
Nous renvoyons enfin l'état du web worker en renvoyant les états de résultat, d'erreur et de chargement :
return {result,error,loading}
Exporter le useWebWorker :
export default useWebWorker;
Vous trouverez ci-dessous le code complet pour hooks/useWebWorker/index.js :
import { useState, useEffect } from "react"; const useWebWorker = (workerFunction, inputData) => { const [result, setResult] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { if (!inputData) return; setLoading(true); setError(null); setResult(null); const blob = new Blob( [ ` self.onmessage = function(event) { (${workerFunction})(event); }; `, ], { type: "application/javascript" } ); const workerScriptUrl = URL.createObjectURL(blob); const worker = new Worker(workerScriptUrl); worker.onmessage = (event) => { console.log("Worker result:", event.data); setResult(event.data); setLoading(false); }; worker.onerror = (event) => { console.error("Worker error:", event.message); setError(event.message); setLoading(false); }; console.log("Posting message to worker:", inputData); worker.postMessage(inputData); return () => { worker.terminate(); URL.revokeObjectURL(workerScriptUrl); }; }, [inputData, workerFunction]); return { result, error, loading }; }; export default useWebWorker;
Dans notre App.jsx, définissons une fonction de travail qui sera exécutée par notre web worker :
const workerFunction = (e) => { const { base, exponent } = e.data; console.log("Worker function received data:", base, exponent); let result = 1; for (let i = 0; i < exponent; i++) { result *= base; } self.postMessage(result); };
e.data contains data from the web worker.
The workerFunction:
Logs the received data (base and exponent).
Computes the power of base raised to exponent.
Sends the result back to the main thread using self.postMessage(result).
Let's now define our App functional component inside our App.jsx:
const App = () => { const [base, setBase] = useState(""); const [exponent, setExponent] = useState(""); const [inputData, setInputData] = useState(null); const { result, error, loading } = useWebWorker(workerFunction, inputData);
base: Stores the base number input.
exponent: Stores the exponent number input.
inputData: Stores the data to be sent to the worker.
Custom Hook Usage: useWebWorker is used to create a Web Worker and manage its state.
const handleBaseChange = (e) => setBase(e.target.value); const handleExponentChange = (e) => setExponent(e.target.value);
handleBaseChange: Updates base state when the input value changes.
handleExponentChange: Updates exponent state when the input value changes
const handleCalculate = () => { setInputData({ base: Number(base), exponent: Number(exponent) }); };
handleCalculate Function: Converts base and exponent to numbers and sets them as inputData for the Web Worker.
return ( <div> <h1>Exponential Calculation with Web Worker</h1> <div> <label> Base: <input type="number" value={base} onChange={handleBaseChange} /> </label> </div> <div> <label> Exponent: <input type="number" value={exponent} onChange={handleExponentChange} /> </label> </div> <button onClick={handleCalculate}>Calculate</button> {loading && <div>Loading...</div>} {error && <div>Error: {error}</div>} {!loading && !error && result !== null && <div>Result: {result}</div>} </div> ); };
JSX Layout:
Displays a title and input fields for base and exponent.
A button triggers the handleCalculate function.
Conditionally renders loading, error, or result messages based on the state.
Below is the complete App.jsx code:
import { useState } from "react"; import useWebWorker from "./hooks/useWebWorker"; import "./App.css"; const workerFunction = (e) => { const { base, exponent } = e.data; console.log("Worker function received data:", base, exponent); let result = 1; for (let i = 0; i < exponent; i++) { result *= base; } self.postMessage(result); }; const App = () => { const [base, setBase] = useState(""); const [exponent, setExponent] = useState(""); const [inputData, setInputData] = useState(null); const { result, error, loading } = useWebWorker(workerFunction, inputData); const handleBaseChange = (e) => setBase(e.target.value); const handleExponentChange = (e) => setExponent(e.target.value); const handleCalculate = () => { setInputData({ base: Number(base), exponent: Number(exponent) }); }; return ( <div> <h1>Exponential Calculation with Web Worker</h1> <div> <label> Base: <input type="number" value={base} onChange={handleBaseChange} /> </label> </div> <div> <label> Exponent: <input type="number" value={exponent} onChange={handleExponentChange} /> </label> </div> <button onClick={handleCalculate}>Calculate</button> {loading && <div>Loading...</div>} {error && <div>Error: {error}</div>} {!loading && !error && result !== null && <div>Result: {result}</div>} </div> ); }; export default App;
We can now use npm run dev to view our project.
Below is a live preview of our project:
Web Workers Project Implementation
Implementing Web Workers in your React applications can significantly enhance performance, especially when dealing with CPU-intensive tasks. By offloading such tasks to background threads, you ensure that your app remains responsive and provides a smooth user experience.
In our example, we've seen how straightforward it can be to set up and use Web Workers in a React environment. From dynamically creating a worker using a custom hook to managing the communication between the main thread and the worker, every step is designed to be both efficient and easy to integrate.
This approach not only helps in maintaining a responsive UI but also makes your app more robust and user-friendly. Whether it's for complex calculations, data processing, or any other heavy lifting, Web Workers can be your go-to solution for multitasking in modern web applications.
Remember, the key to a great user experience is not just about what your app does but how it feels while doing it. By implementing Web Workers, you can ensure that your app feels snappy and responsive, keeping your users happy and engaged. So, go ahead and explore the power of Web Workers in your next React project – your users will thank you for it!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!