Heim  >  Artikel  >  Web-Frontend  >  Verwendung von Web Workern für die Hintergrundverarbeitung in React Hooks-Anwendungen.

Verwendung von Web Workern für die Hintergrundverarbeitung in React Hooks-Anwendungen.

WBOY
WBOYOriginal
2024-07-24 21:09:511055Durchsuche

1.0 Einführung

Web Worker in React sind Funktionen, die die gleichzeitige Ausführung mehrerer Threads in einer React-Anwendung ermöglichen. Sie ermöglichen die Ausführung einiger Threads im Hintergrund, um sie von der Ausführung als Teil des Hauptthreads auszuschließen.

Angenommen, Sie haben eine Anwendung, in der Sie möglicherweise eine komplexe Berechnung durchführen, große Datenmengen von einer API abrufen oder eine Hintergrundbenachrichtigung implementieren möchten, ohne die normale Funktionalität des aktuell ausgeführten Hauptthreads zu ändern. Dies kann durch die Implementierung von React Web Hooks erreicht werden, die sicherstellen, dass die Benutzeroberfläche nicht einfriert, während alle diese Prozesse in einer React-App ausgeführt werden.

In diesem Leitfaden erstellen wir ein Beispiel-React-Projekt, das Web-Worker in benutzerdefinierten React-Hooks implementiert, um eine Exponentialberechnung durchzuführen.

Schritte

Schritt 1: Erstellen Sie die React-App

Erstellen Sie eine Reaktionsanwendung.

npx create-vite myproject -- --template react

Ich bevorzuge die Verwendung von Vite zum Erstellen einer React-App, da diese im Vergleich zur Create-React-App eine schnellere Laufzeit hat.
Hier verwenden wir „react“ als Vorlage von vite.

Select React as your template

JavaScript auswählen:

Select Variant as JavaScript

Utilizing Web Workers for Background Processing in React Hooks Applications.

Öffnen Sie das Projekt in einem Editor. (Ich verwende Vs-Code für dieses Projekt)

code .

Schritt 2: Gerüstbau für unser Projekt.

Erstellen Sie im src-Verzeichnis ein weiteres Verzeichnis „hooks/useWebWorkers“.
Erstellen Sie in diesem Ordner eine index.js-Datei, die unseren Web-Worker wie unten gezeigt enthält:

Utilizing Web Workers for Background Processing in React Hooks Applications.

Schritt 3: Erstellen unseres Web-Workers

In unserem /hooks/useWebWorker/index.js erstellen wir einen benutzerdefinierten Hook, der unseren Web-Worker erstellt

Erstellen Sie einen benutzerdefinierten useWebWorker-Hook, der workerFunction und inputData als Parameter verwendet.

const useWebWorker =(workerFunction,inputData)=>{

}
export default useWebWorker;

Initialisieren Sie Zustände für unser Ergebnis, unseren Fehler und den Status unseres Web-Workers mit dem useState-Hook.

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) Ergebnis speichert das Ergebnis unseres Web-Workers. Anfangs auf null gesetzt.

ii)error verfolgt den Fehler, der im Web-Worker auftreten kann. Anfangs auf null gesetzt.

iii) Beim Laden wird der Status unseres Web-Workers angezeigt, unabhängig davon, ob er Daten verarbeitet oder nicht. Anfangs auf „false“ gesetzt.

Initialisieren Sie einen useEffect, um unseren Web-Worker zu halten.

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;

Der useEffect-Hook wird immer dann ausgeführt, wenn sich inputData ändert, da er als Trennzeichen festgelegt wurde,
Wenn die Eingabedaten null oder undefiniert sind, wird der Hook vorzeitig beendet.

if(!inputData)return;

Stellen Sie sicher, dass alle Zustände korrekt zurückgesetzt werden

    setLoading(true);
    setError(null);
    setResult(null);

Erstellen Sie ein Web-Worker-Blob

    const blob = new Blob(
      [
        `
          self.onmessage = function(event) {
            (${workerFunction.toString()})(event);
          };
        `,
      ],
      { type: "application/javascript" }
    );

Konvertiert workerFunction in eine Zeichenfolge und fügt sie in ein Blob-Objekt ein. Dieser Blob stellt den JavaScript-Code dar, der im Web Worker ausgeführt wird.

Erstellen Sie einen Worker, der eine URL für den Blob generiert und unter Verwendung dieser URL einen neuen Web Worker erstellt:

    const workerScriptUrl = URL.createObjectURL(blob);
    const worker = new Worker(workerScriptUrl);

Richten Sie einen Ereignishandler für die vom Worker ausgegebene Nachricht ein.

worker.onmessage(event){

}

Wenn der Web-Worker eine Nachricht an den Hauptthread sendet (mithilfe von postMessage), wird der Ereignishandler ausgelöst.
event.data enthält entweder ein gültiges Ergebnis oder einen Fehler im Web-Worker. Wir kümmern uns um die Darstellung entweder des Fehlers oder der gültigen Ergebnisse innerhalb der if-else-Anweisungen.

Im Fehlerfall setzen wir den Fehler in setError() auf event.data.error.
Wenn gültige Ergebnisse zurückgegeben werden, übergeben wir das Ergebnis an event.data innerhalb von setResult()

    worker.onmessage = (event) => {
      console.log("Worker result:", event.data);
      if (event.data.error) {
        setError(event.data.error);
      } else {
        setResult(event.data);
      }
      setLoading(false);
    };

Setzt das Laden auf „false“, wenn es fertig ist.

Behandeln Sie Web-Worker-Fehler:

Wir verwenden worker.onerror(event){

}
Wir übergeben das Ereignis als Parameter, aktualisieren den Fehler auf „event.message“ und aktualisieren den Ladestatus auf „false“.

    worker.onerror = (event) => {
      console.error("Worker error:", event.message);
      setError(event.message);
      setLoading(false);
    };

Wir senden nun die Eingabedaten an den Web-Worker

worker.postMessage(inputData);

Wir beenden den Web Worker und widerrufen die Blob-URL, wenn die Bereitstellung der Komponente aufgehoben wird oder sich inputData oder workerFunction ändert:

    return () => {
      worker.terminate();
      URL.revokeObjectURL(workerScriptUrl);
    };
  }, [inputData, workerFunction]);

Wir geben schließlich den Status des Web-Workers zurück, indem wir Ergebnis-, Fehler- und Ladestatus zurückgeben:

return {result,error,loading}

Exportieren Sie den useWebWorker:

export default useWebWorker;

Unten finden Sie den vollständigen Code für „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;

Schritt 4: Bearbeiten unserer App.jsx

In unserer App.jsx definieren wir eine Worker-Funktion, die von unserem Web-Worker ausgeführt wird:

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

Conclusion

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!

Das obige ist der detaillierte Inhalt vonVerwendung von Web Workern für die Hintergrundverarbeitung in React Hooks-Anwendungen.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn