Konkreter Anwendungsfall für Web Worker

<ph type="x-smartling-placeholder">

Im letzten Modul haben wir einen Überblick über Web Worker erhalten. Web Worker können die Eingabereaktionsfähigkeit verbessern, indem JavaScript aus dem Hauptthread separate Web Worker-Threads, wodurch Sie die Interaktion der Nutzer mit Ihrer Website verbessern können. auf Next Paint (INP) umstellen, wenn Ihre Arbeit keinen direkten Zugriff auf das im Hauptthread. Eine Übersicht allein reicht jedoch nicht aus. wird ein konkreter Anwendungsfall für einen Web Worker angeboten.

Ein Beispiel hierfür wäre eine Website, die EXIF-Metadaten aus einer ist kein so weit hergeholtes Konzept. Websites wie Flickr bieten sogar können Nutzer die EXIF-Metadaten aufrufen, um technische Details zur wie Farbtiefe, Marke und Modell der Kamera Daten.

Die Logik zum Abrufen eines Bildes und seiner Konvertierung in ein ArrayBuffer-Element jedoch Das Extrahieren der EXIF-Metadaten könnte teuer sein, im Hauptthread. Glücklicherweise ermöglicht der Web Worker-Bereich aus dem Hauptthread entfernt. Mithilfe der Messaging-Pipeline des Web Workers EXIF-Metadaten werden als HTML-String an den Hauptthread zurückgesendet und die der Nutzer sieht.

So sieht der Hauptthread ohne Web Worker aus

Sehen Sie sich zunächst an, wie der Hauptthread aussieht, wenn wir das ohne Web Worker. Führen Sie dazu die folgenden Schritte aus:

  1. Öffne einen neuen Tab in Chrome und öffne die zugehörigen Entwicklertools.
  2. Öffnen Sie den Bereich „Leistung“.
  3. Rufen Sie https://exif-worker.glitch.me/without-worker.html auf.
  4. Klicken Sie im Bereich „Leistung“ rechts oben im Entwicklertools-Bereich.
  5. Fügen Sie diesen Bildlink ein oder einen anderen Ihrer Wahl, der die EXIF-Datei enthält. Metadaten – in das Feld und klicken Sie auf die Schaltfläche JPEG herunterladen!.
  6. Sobald die EXIF-Metadaten in die Schnittstelle aufgenommen wurden, klicken Sie noch einmal auf Record (Aufzeichnen). Aufzeichnung beenden.
<ph type="x-smartling-placeholder">
</ph> Der Performance-Profiler, der die Aktivität der Anwendung für Bildmetadaten-Extraktoren anzeigt, die vollständig im Hauptthread auftreten Es gibt zwei wesentliche lange Aufgaben: eine, die einen Abruf ausführt, um das angeforderte Bild abzurufen und zu decodieren, und eine, die die Metadaten aus dem Bild extrahiert. <ph type="x-smartling-placeholder">
</ph> Hauptthread-Aktivität in der Anwendung für Bildmetadatenextraktoren. Beachten Sie, dass alle findet die Aktivität im Hauptthread statt.

Beachten Sie, dass neben anderen Threads, die möglicherweise vorhanden sind, wie z. B. Rasterizer, und so weiter: In der App findet alles im Hauptthread statt. Auf der Hauptseite passiert Folgendes:

  1. Das Formular nimmt die Eingabe entgegen und sendet eine fetch-Anfrage, um die ursprüngliche des Bilds, das die EXIF-Metadaten enthält.
  2. Die Bilddaten werden in ein ArrayBuffer konvertiert.
  3. Das Skript exif-reader wird verwendet, um die EXIF-Metadaten aus der Bild.
  4. Die Metadaten werden extrahiert, um einen HTML-String zu erstellen, der dann das Feld Metadaten-Viewer.

Dies lässt sich mit einer Implementierung desselben Verhaltens vergleichen, Arbeiter!

So sieht der Hauptthread mit einem Web Worker aus

Jetzt wissen Sie, wie das Extrahieren der EXIF-Metadaten aus einem JPEG-Datei im Hauptthread an. Worker enthalten ist:

  1. Öffnen Sie einen weiteren Tab in Chrome und dann die zugehörigen Entwicklertools.
  2. Öffnen Sie den Bereich „Leistung“.
  3. Rufen Sie https://exif-worker.glitch.me/with-worker.html auf.
  4. Klicken Sie rechts oben im Leistungsbereich auf die Schaltfläche zum Aufzeichnen. des Bereichs „Entwicklertools“ aus.
  5. Fügen Sie diesen Bildlink in das Feld ein und klicken Sie auf die Schaltfläche JPEG herunterladen!.
  6. Sobald die EXIF-Metadaten auf der Oberfläche angezeigt werden, klicken Sie auf die Schaltfläche Aufzeichnen. noch einmal, um die Aufzeichnung zu beenden.
<ph type="x-smartling-placeholder">
</ph> Der Performance-Profiler, der die Aktivität der Anwendung für die Bildmetadatenextraktion anzeigt, die sowohl im Hauptthread als auch in einem Web Worker-Thread auftritt. Auch wenn es immer noch lange Aufgaben im Hauptthread gibt, sind diese deutlich kürzer, da das Abrufen/Decodieren von Bildern und die Metadatenextraktion vollständig in einem Web Worker-Thread ausgeführt werden. Die einzige Hauptthread-Arbeit umfasst die Übergabe von Daten an den und vom Web Worker. <ph type="x-smartling-placeholder">
</ph> Hauptthread-Aktivität in der Anwendung für Bildmetadatenextraktoren. Beachten Sie, dass es einen zusätzlichen Web Worker-Thread, in dem die meiste Arbeit erledigt wird.

Dies ist die Leistungsfähigkeit eines Web Workers. Anstatt alle Hauptaufgaben Alles außer dem Befüllen des Metadaten-Viewers mit HTML erfolgt auf einer separaten Thread. Das bedeutet, dass der Hauptthread für andere Aufgaben freigegeben wird.

Der vielleicht größte Vorteil dieser App besteht darin, keinen Web Worker verwendet, wird das Skript exif-reader nicht auf der sondern im Web Worker-Thread. Das bedeutet, dass die Kosten Das Herunterladen, Parsen und Kompilieren des exif-reader-Skripts erfolgt außerhalb des im Hauptthread.

Sehen wir uns nun den Web Worker-Code genauer an, der dies ermöglicht.

Ein Blick auf den Web Worker-Code

Es reicht nicht aus, den Unterschied eines Web Workers zu sehen. Es hilft auch, um zu verstehen, wie dieser Code aussieht, um zu wissen, Web Worker-Bereich möglich.

<ph type="x-smartling-placeholder">

Beginnen Sie mit dem Code des Hauptthreads, der erstellt werden muss, bevor der Web Worker kann Bild eingeben:

// scripts.js

// Register the Exif reader web worker:
const exifWorker = new Worker('/js/with-worker/exif-worker.js');

// We have to send image requests through this proxy due to CORS limitations:
const imageFetchPrefix = 'https://res.cloudinary.com/demo/image/fetch/';

// Necessary elements we need to select:
const imageFetchPanel = document.getElementById('image-fetch');
const imageExifDataPanel = document.getElementById('image-exif-data');
const exifDataPanel = document.getElementById('exif-data');
const imageInput = document.getElementById('image-url');

// What to do when the form is submitted.
document.getElementById('image-form').addEventListener('submit', event => {
  // Don't let the form submit by default:
  event.preventDefault();

  // Send the image URL to the web worker on submit:
  exifWorker.postMessage(`${imageFetchPrefix}${imageInput.value}`);
});

// This listens for the Exif metadata to come back from the web worker:
exifWorker.addEventListener('message', ({ data }) => {
  // This populates the Exif metadata viewer:
  exifDataPanel.innerHTML = data.message;
  imageFetchPanel.style.display = 'none';
  imageExifDataPanel.style.display = 'block';
});

Dieser Code wird im Hauptthread ausgeführt und richtet das Formular zum Senden der Bild-URL an Web Worker. Von dort beginnt der Web Worker-Code mit dem Präfix importScripts. -Anweisung, die das externe exif-reader-Skript lädt und dann das Messaging-Pipeline zum Hauptthread:

// exif-worker.js

// Import the exif-reader script:
importScripts('/js/with-worker/exifreader.js');

// Set up a messaging pipeline to send the Exif data to the `window`:
self.addEventListener('message', ({ data }) => {
  getExifDataFromImage(data).then(status => {
    self.postMessage(status);
  });
});
<ph type="x-smartling-placeholder">

Dieser JavaScript-Code richtet die Messaging-Pipeline ein, sodass Nutzer, die das Formular mit einer URL an eine JPEG-Datei sendet, kommt die URL im Web Worker an. Von dort extrahiert dieser nächste Code-Snippet die EXIF-Metadaten aus der JPEG-Datei, erstellt einen HTML-String und sendet diesen HTML-Code zurück an die window, damit er schließlich angezeigt:

// Takes a blob to transform the image data into an `ArrayBuffer`:
// NOTE: these promises are simplified for readability, and don't include
// rejections on failures. Check out the complete web worker code:
// https://glitch.com/edit/#!/exif-worker?path=js%2Fwith-worker%2Fexif-worker.js%3A10%3A5
const readBlobAsArrayBuffer = blob => new Promise(resolve => {
  const reader = new FileReader();

  reader.onload = () => {
    resolve(reader.result);
  };

  reader.readAsArrayBuffer(blob);
});

// Takes the Exif metadata and converts it to a markup string to
// display in the Exif metadata viewer in the DOM:
const exifToMarkup = exif => Object.entries(exif).map(([exifNode, exifData]) => {
  return `
    <details>
      <summary>
        <h2>${exifNode}</h2>
      </summary>
      <p>${exifNode === 'base64' ? `<img src="data:image/jpeg;base64,${exifData}">` : typeof exifData.value === 'undefined' ? exifData : exifData.description || exifData.value}</p>
    </details>
  `;
}).join('');

// Fetches a partial image and gets its Exif data
const getExifDataFromImage = imageUrl => new Promise(resolve => {
  fetch(imageUrl, {
    headers: {
      // Use a range request to only download the first 64 KiB of an image.
      // This ensures bandwidth isn't wasted by downloading what may be a huge
      // JPEG file when all that's needed is the metadata.
      'Range': `bytes=0-${2 ** 10 * 64}`
    }
  }).then(response => {
    if (response.ok) {
      return response.clone().blob();
    }
  }).then(responseBlob => {
    readBlobAsArrayBuffer(responseBlob).then(arrayBuffer => {
      const tags = ExifReader.load(arrayBuffer, {
        expanded: true
      });

      resolve({
        status: true,
        message: Object.values(tags).map(tag => exifToMarkup(tag)).join('')
      });
    });
  });
});

Es ist ein wenig zu lesen, aber dies ist auch ein ziemlich verwickelter Anwendungsfall für Web Worker. Die Ergebnisse sind jedoch die Arbeit wert und nicht nur auf diesen Anwendungsfall beschränkt. Sie können Web Worker für verschiedenste Zwecke verwenden, z. B. zum Isolieren von fetch-Aufrufen und Antworten verarbeiten und große Datenmengen verarbeiten, ohne Hauptthread – und das ist nur für den Anfang.

Wenn Sie die Leistung Ihrer Webanwendungen verbessern, sollten Sie alles, was in einem Web Worker-Kontext vernünftigerweise möglich ist. Die Gewinne könnten und können zu einer insgesamt besseren Nutzererfahrung auf Ihrer Website führen.