Un caso de uso concreto de un trabajador web

En el último módulo, se proporcionó una descripción general de los trabajadores web. Los trabajadores web pueden mejorar la capacidad de respuesta de la entrada moviendo JavaScript fuera del subproceso principal conversaciones separadas del trabajador web, lo que puede ayudar a mejorar la Interacción del sitio web a Next Paint (INP) cuando tengas trabajos que no necesitan acceso directo subproceso principal. Sin embargo, una descripción general por sí sola no es suficiente. En este módulo, un caso de uso concreto para un trabajador web.

Un caso de uso como este podría ser un sitio web que necesita quitar los metadatos EXIF de una no es un concepto tan descabellado. De hecho, sitios web como Flickr ofrecen usuarios una forma de ver los metadatos EXIF para conocer detalles técnicos sobre el imágenes que alojan, como la profundidad de color, la marca y el modelo de la cámara, y otras de datos no estructurados.

Sin embargo, la lógica para recuperar una imagen y convertirla en un ArrayBuffer y extraer los metadatos EXIF podría ser potencialmente costoso si se hace por completo en el subproceso principal. Afortunadamente, el alcance del trabajador web permite realizar este trabajo. fuera del subproceso principal. Luego, con la canalización de mensajería del trabajador web, Los metadatos EXIF se transmiten de vuelta al subproceso principal como una cadena HTML. que se le muestran al usuario.

Cómo se ve el subproceso principal sin un trabajador web

Primero, observa cómo se ve el subproceso principal cuando hacemos este trabajo sin un trabajador web. Para hacerlo, sigue estos pasos:

  1. Abre una nueva pestaña en Chrome y abre las Herramientas para desarrolladores.
  2. Abre el panel de rendimiento.
  3. Navega a https://exif-worker.glitch.me/without-worker.html.
  4. En el panel de rendimiento, haz clic en Grabar en la esquina superior derecha de el panel de Herramientas para desarrolladores.
  5. Pega este vínculo de imagen o uno de tu elección que contenga EXIF en el campo y haz clic en el botón Get that JPEG!.
  6. Cuando la interfaz se propague con los metadatos EXIF, vuelve a hacer clic en Record para deja de grabar.
El generador de perfiles de rendimiento muestra la actividad de la app de extractor de metadatos de imagen que ocurre completamente en el subproceso principal. Existen dos tareas muy largas: una que ejecuta una recuperación para obtener la imagen solicitada y la decodifica, y otra que extrae los metadatos de la imagen.
Actividad del subproceso principal en la app de extracción de metadatos de imágenes. Ten en cuenta que todas la actividad se produce en el subproceso principal.

Ten en cuenta que, además de otros subprocesos que puedan estar presentes, como el subprocesos, etcétera. Todo el contenido de la app ocurre en el subproceso principal. En la página principal subproceso, sucederá lo siguiente:

  1. El formulario toma la entrada y envía una solicitud fetch para obtener la de la imagen que contiene los metadatos EXIF.
  2. Los datos de la imagen se convierten en un ArrayBuffer.
  3. La secuencia de comandos exif-reader se usa para extraer los metadatos EXIF del imagen.
  4. Los metadatos se extraen para construir una cadena HTML, que luego completa la visualizador de metadatos.

Comparemos eso con una implementación del mismo comportamiento, pero trabajador.

Cómo se ve el subproceso principal con un trabajador web

Ahora que has visto cómo es extraer los metadatos EXIF de un JPEG en el subproceso principal, observa cómo se ve cuando una página web Worker está en la mezcla:

  1. Abre otra pestaña en Chrome y abre las Herramientas para desarrolladores.
  2. Abre el panel de rendimiento.
  3. Navega a https://exif-worker.glitch.me/with-worker.html.
  4. En el panel de rendimiento, haz clic en el botón de grabación en la parte superior derecha. en la esquina superior del panel de Herramientas para desarrolladores.
  5. Pega este vínculo de imagen en el campo y haz clic en el botón Obtener ese archivo JPEG!.
  6. Una vez que la interfaz se propague con los metadatos EXIF, haz clic en el botón Record. de nuevo para detener la grabación.
El Generador de perfiles de rendimiento muestra la actividad de la app de extractor de metadatos de imágenes que ocurre tanto en el subproceso principal como en un subproceso de trabajador web. Si bien todavía existen tareas largas en el subproceso principal, son sustancialmente más cortas: la recuperación y decodificación de imágenes y la extracción de metadatos ocurre completamente en un subproceso de trabajador web. El único trabajo de subprocesos principal implica pasar datos hacia y desde el trabajador web.
Actividad del subproceso principal en la app de extracción de metadatos de imágenes. Ten en cuenta que hay un subproceso de trabajador web adicional en el que se realiza la mayor parte del trabajo.

Esta es la potencia de un trabajador web. En lugar de hacer todo de manera principal subproceso, todo excepto completar el visualizador de metadatos con HTML se hace en un subproceso separado. Esto significa que el subproceso principal se libera para realizar otras tareas.

Quizás la mayor ventaja es que, a diferencia de la versión de esta app no utiliza un trabajador web, la secuencia de comandos exif-reader no se carga en la instancia principal sino más bien en el subproceso del trabajador web. Esto significa que el costo la descarga, el análisis y la compilación de la secuencia de comandos exif-reader se realiza desde la subproceso principal.

Ahora, veamos el código del trabajador web que hace que todo esto sea posible.

Un vistazo al código del trabajador web

No basta con ver la diferencia que marca un trabajador web; también es útil al menos en este caso, cómo se ve ese código para que sepas como es posible en el alcance del trabajador web.

Comience con el código del subproceso principal que debe ocurrir antes de que el trabajador web pueda hacerlo. ingresa a la imagen:

// 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';
});

Este código se ejecuta en el subproceso principal y configura el formulario para que se envíe la URL de la imagen a el trabajador web. Desde allí, el código del trabajador web comienza con un importScripts. que carga la secuencia de comandos exif-reader externa y, luego, configura la de mensajería al subproceso principal:

// 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);
  });
});

Este bit de JavaScript configura la canalización de mensajería para que, cuando el usuario envía el formulario con una URL a un archivo JPEG, y la URL llega al trabajador web. A partir de ahí, el siguiente fragmento de código extrae los metadatos EXIF del archivo JPEG, compila una cadena HTML y envía ese HTML de vuelta al window para que, finalmente, se que se le muestran al usuario:

// 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 un poco para leer, pero también es un caso de uso bastante involucrado para los trabajadores web. Sin embargo, los resultados valen el trabajo y no solo se limitan a este caso de uso. Puedes usar trabajadores web para todo tipo de tareas, como aislar llamadas fetch. y procesar respuestas, lo que permite procesar grandes cantidades de datos sin bloquear la hilo principal, y eso es solo para principiantes.

Para mejorar el rendimiento de tus aplicaciones web, empieza a pensar en cualquier cosa que se pueda hacer razonablemente en el contexto de un trabajador web. Las ganancias podrían ser sea significativo y puede conducir a una mejor experiencia del usuario en general para su sitio web.