กรณีการใช้งานของ Web Worker ที่เป็นรูปธรรม

ในโมดูลสุดท้าย เราได้ให้ภาพรวมของผู้ปฏิบัติงานบนเว็บ ผู้ปฏิบัติงานเกี่ยวกับเว็บทำได้ ปรับปรุงการตอบสนองของอินพุตโดยย้าย JavaScript ออกจากเทรดหลักไปยัง ชุดข้อความของ Web Worker แยกต่างหาก ซึ่งจะช่วยปรับปรุงการโต้ตอบของเว็บไซต์ของคุณ ไปยัง Next Paint (INP) เมื่อมีงานที่ไม่จำเป็นต้องเข้าถึง เทรดหลัก อย่างไรก็ตาม ภาพรวมเพียงอย่างเดียวนั้นไม่เพียงพอ และในโมดูลนี้ เราได้นำเสนอกรณีการใช้งานที่เป็นรูปธรรมสำหรับ Web Worker

กรณีการใช้งานหนึ่งอาจเป็นเว็บไซต์ที่ต้องตัดข้อมูลเมตา Exif ออกจากไฟล์ รูปภาพ นี่ไม่ใช่แนวคิดที่แพร่หลายเกินไป ที่จริงแล้ว เว็บไซต์อย่าง Flickr วิธีการดูข้อมูลเมตาของ Exif เพื่อศึกษารายละเอียดทางเทคนิคเกี่ยวกับ รูปภาพ เช่น ความลึกของสี ยี่ห้อและรุ่นของกล้อง และอื่นๆ

แต่ตรรกะในการดึงรูปภาพจะแปลงเป็น ArrayBuffer และการแยกข้อมูลเมตาของ Exif อาจมีค่าใช้จ่ายสูงหากดำเนินการทั้งหมด ในเทรดหลัก โชคดีที่ขอบเขตของ Web Worker ช่วยให้เราทำงานนี้ได้ ออกจากชุดข้อความหลัก จากนั้น โดยใช้ไปป์ไลน์การรับส่งข้อความของผู้ปฏิบัติงานเว็บ ระบบจะส่งข้อมูลเมตา Exif กลับไปยังเทรดหลักเป็นสตริง HTML และ แสดงต่อผู้ใช้

ลักษณะของเทรดหลักเมื่อไม่มี Web Worker

ขั้นแรก ให้สังเกตลักษณะของเทรดหลักเมื่อเราดำเนินการนี้โดยไม่มี Web Worker ในการดำเนินการ ให้ทำตามขั้นตอนต่อไปนี้

  1. เปิดแท็บใหม่ใน Chrome แล้วเปิดเครื่องมือสำหรับนักพัฒนาเว็บ
  2. เปิดแผงประสิทธิภาพ
  3. ไปที่ https://exif-worker.glitch.me/without-worker.html
  4. ในแผงประสิทธิภาพ ให้คลิกบันทึกที่มุมขวาบนของ แผงเครื่องมือสำหรับนักพัฒนาเว็บ
  5. วางลิงก์รูปภาพนี้หรือลิงก์อื่นที่คุณเลือกที่มี Exif ข้อมูลเมตา - ในช่องแล้วคลิกปุ่ม Get that JPEG!
  6. เมื่ออินเทอร์เฟซมีข้อมูลเมตา Exif แล้ว ให้คลิก Record อีกครั้งเพื่อ หยุดบันทึก
เครื่องมือสร้างโปรไฟล์ประสิทธิภาพที่แสดงกิจกรรมของแอปเครื่องมือแยกข้อมูลเมตาของรูปภาพที่เกิดขึ้นทั้งหมดในเทรดหลัก งานที่มีนัยสำคัญมี 2 งาน งานแรกคือการเรียกใช้การดึงข้อมูลเพื่อรับรูปภาพที่ขอและถอดรหัส ส่วนอีกงานคือดึงข้อมูลเมตาจากรูปภาพ
กิจกรรมเทรดหลักในแอปเครื่องมือแยกข้อมูลเมตาของรูปภาพ โปรดทราบว่า กิจกรรมจะเกิดขึ้นในเทรดหลัก

โปรดทราบว่านอกเหนือจากชุดข้อความอื่นๆ ที่อาจมีอยู่ เช่น โปรแกรมแรสเตอร์ เทรด และอื่นๆ เช่น ทุกอย่างในแอปจะเกิดขึ้นบนเทรดหลัก บน เทรด สิ่งต่อไปนี้จะเกิดขึ้น

  1. แบบฟอร์มจะรับอินพุตและส่งคำขอ fetch เพื่อรับข้อมูลเบื้องต้น ในรูปภาพที่มีข้อมูลเมตา Exif
  2. ระบบจะแปลงข้อมูลรูปภาพเป็น ArrayBuffer
  3. สคริปต์ exif-reader จะใช้เพื่อดึงข้อมูลเมตา Exif จาก รูปภาพ
  4. ข้อมูลเมตาจะถูกคัดลอกเพื่อสร้างสตริง HTML ซึ่งจะป้อนข้อมูล ผู้ดูข้อมูลเมตา

ซึ่งแตกต่างจากการใช้ลักษณะการทำงานแบบเดียวกัน แต่ใช้เว็บ ผู้ปฏิบัติงาน!

ลักษณะของเทรดหลักกับ Web Worker

ตอนนี้คุณก็ได้เห็นหน้าตาของการดึงข้อมูลข้อมูลเมตา Exif จาก ไฟล์ JPEG ในชุดข้อความหลัก ลองดูว่าไฟล์จะมีลักษณะอย่างไรเมื่อ คนทำงานแบบผสมผสาน:

  1. เปิดแท็บอื่นใน Chrome แล้วเปิดเครื่องมือสำหรับนักพัฒนาเว็บในแท็บนั้น
  2. เปิดแผงประสิทธิภาพ
  3. ไปที่ https://exif-worker.glitch.me/with-worker.html
  4. ในแผงประสิทธิภาพ ให้คลิกปุ่มบันทึกที่ด้านขวาบน มุมของแผงเครื่องมือสำหรับนักพัฒนาเว็บ
  5. วางลิงก์รูปภาพนี้ในช่อง และคลิกปุ่มรับ JPEG!
  6. เมื่ออินเทอร์เฟซสร้างข้อมูลเมตา Exif แล้ว ให้คลิกปุ่มบันทึก อีกครั้งเพื่อหยุดบันทึก
เครื่องมือสร้างโปรไฟล์ประสิทธิภาพที่แสดงกิจกรรมของแอปเครื่องมือแยกข้อมูลเมตาของรูปภาพที่เกิดขึ้นทั้งในเทรดหลักและเทรดของผู้ปฏิบัติงานบนเว็บ แม้ว่ายังมีงานที่ใช้เวลานานในเทรดหลัก แต่ก็ใช้เวลาสั้นกว่านั้นมาก โดยการดึงข้อมูล/ถอดรหัสรูปภาพและการดึงข้อมูลเมตาจะเกิดขึ้นทั้งหมดในเทรดของผู้ปฏิบัติงานบนเว็บ งานของเทรดหลักเพียงอย่างเดียวต้องส่งข้อมูลไปยังและจาก Web Worker
กิจกรรมเทรดหลักในแอปเครื่องมือแยกข้อมูลเมตาของรูปภาพ โปรดทราบว่ามี เทรดเพิ่มเติมของ Web Worker ซึ่งส่วนใหญ่ทำงานเสร็จแล้ว

นี่คือศักยภาพของ Web Worker แทนที่จะทำทุกอย่างบน เทรดทุกอย่าง ยกเว้นการสร้างโปรแกรมดูข้อมูลเมตาด้วย HTML นั้นทำใน ชุดข้อความแยกต่างหาก ซึ่งหมายความว่าเทรดหลักจะใช้เพื่อทำงานอื่นๆ ได้

ข้อดีที่สำคัญที่สุดของที่นี่คือ ไม่ได้ใช้ Web Worker สคริปต์ exif-reader จะไม่โหลดในหน้าหลัก แต่อยู่ในเทรดของ Web Worker ซึ่งหมายความว่าต้นทุน การดาวน์โหลด แยกวิเคราะห์ และคอมไพล์สคริปต์ exif-reader จะเกิดขึ้นนอก เทรดหลัก

ตอนนี้ถึงเวลาเจาะลึกเกี่ยวกับโค้ดของ Web Worker ที่ทำให้ทั้งหมดนี้เกิดขึ้นได้!

ดูโค้ดของ Web Worker

การได้เห็นความแตกต่างของผู้ปฏิบัติงานเว็บเพียงอย่างเดียวนั้นยังไม่เพียงพอ การทำเช่นนี้ยังช่วย อย่างน้อยก็ในกรณีนี้คือ โค้ดนั้นหน้าตาเป็นอย่างไร เพื่อให้คุณทราบว่า ที่เป็นไปได้ในขอบเขต Web Worker

เริ่มต้นด้วยรหัสเทรดหลักที่จำเป็นก่อนที่ Web Worker จะสามารถทำได้ เข้าสู่ภาพ:

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

โค้ดนี้จะทำงานในเทรดหลัก และตั้งค่าแบบฟอร์มเพื่อส่ง URL รูปภาพไป Web Worker จากนั้น รหัส Web Worker จะขึ้นต้นด้วย importScripts ที่โหลดสคริปต์ exif-reader ภายนอก จากนั้นตั้งค่า ไปป์ไลน์การรับส่งข้อความไปยังเทรดหลัก

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

JavaScript ส่วนนี้จะตั้งค่าไปป์ไลน์การรับส่งข้อความเพื่อให้เมื่อผู้ใช้ ส่งแบบฟอร์มที่มี URL ไปยังไฟล์ JPEG โดยที่ URL จะมาถึงใน Web Worker จากนั้น โค้ดบิตถัดไปนี้จะดึงข้อมูลเมตา Exif จากไฟล์ JPEG สร้างสตริง HTML และส่ง HTML นั้นกลับไปที่ window แสดงต่อผู้ใช้:

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

แม้จะเป็นเอกสารที่อ่านได้เล็กน้อย แต่นี่เป็นกรณีการใช้งานที่ค่อนข้างเกี่ยวข้องสำหรับผู้ปฏิบัติงานบนเว็บด้วย แต่ผลลัพธ์ที่ได้นั้นคุ้มค่ากับการลงทุน ไม่ใช่เพียงกรณีการใช้งานนี้เท่านั้น คุณสามารถใช้ผู้ปฏิบัติงานบนเว็บได้ทุกอย่าง เช่น การแยกการโทร fetch รายการ และการประมวลผลคำตอบ การประมวลผลข้อมูลจำนวนมากโดยไม่บล็อก เทรดหลัก ซึ่งเป็นข้อมูลเริ่มต้นเท่านั้น

เมื่อปรับปรุงประสิทธิภาพเว็บแอปพลิเคชันของคุณ ให้เริ่มนึกถึง อะไรก็ตามที่สามารถทำได้อย่างสมเหตุสมผลในบริบทของผู้ปฏิบัติงานเว็บ สิ่งที่ได้รับอาจเป็น มีนัยสำคัญ และอาจนำไปสู่ประสบการณ์โดยรวมที่ดีขึ้นสำหรับผู้ใช้สำหรับเว็บไซต์ของคุณ