कंक्रीट वेब वर्कर के इस्तेमाल का उदाहरण

आखिरी मॉड्यूल में, वेब वर्कर की खास जानकारी दी गई थी. वेब वर्कर, JavaScript को मुख्य थ्रेड से बाहर ले जाकर, इनपुट का रिस्पॉन्स बेहतर कर सकता है. ऐसा करने के लिए, वेब वर्कर के थ्रेड को अलग करना होगा. इससे आपकी वेबसाइट के इंटरैक्शन टू नेक्स्ट पेंट (आईएनपी) को बेहतर तरीके से ऐक्सेस किया जा सकता है. हालांकि, सिर्फ़ खास जानकारी ही काफ़ी नहीं है. इस मॉड्यूल में, वेब वर्कर के लिए एक बेहतर इस्तेमाल का उदाहरण दिया गया है.

ऐसा ही एक वेबसाइट ऐसी वेबसाइट हो सकती है जिसके लिए किसी इमेज से Exif मेटाडेटा को हटाना ज़रूरी हो. यह ऐसा कॉन्सेप्ट नहीं है जो आम तौर पर साफ़ तौर पर पता न चलता हो. असल में, Flickr जैसी वेबसाइटें, उपयोगकर्ताओं को Exif मेटाडेटा देखने का तरीका मुहैया कराती हैं. इससे, उन्हें होस्ट की जाने वाली इमेज के बारे में तकनीकी जानकारी मिलती है, जैसे कि रंग की गहराई, कैमरा बनाने, और मॉडल वगैरह.

हालांकि, अगर मुख्य थ्रेड पर इमेज को फ़ेच करने, उसे ArrayBuffer में बदलने, और Exif मेटाडेटा को निकालने का लॉजिक इस्तेमाल किया जाता है, तो यह काफ़ी महंगा हो सकता है. अच्छी बात यह है कि वेब वर्कर के स्कोप की मदद से, मुख्य थ्रेड से यह काम पूरा किया जा सकता है. इसके बाद, वेब वर्कर की मैसेजिंग पाइपलाइन का इस्तेमाल करके, Exif मेटाडेटा को मुख्य थ्रेड में वापस एक एचटीएमएल स्ट्रिंग के रूप में भेजा जाता है और उपयोगकर्ता को दिखाया जाता है.

वेब वर्कर के बिना, मुख्य थ्रेड कैसी दिखती है

सबसे पहले, देखें कि जब हम वेब वर्कर के बिना यह काम करते हैं, तो मुख्य थ्रेड कैसा दिखता है. ऐसा करने के लिए, नीचे दिया गया तरीका अपनाएं:

  1. Chrome में एक नया टैब खोलें और इसका DevTools खोलें.
  2. परफ़ॉर्मेंस पैनल खोलें.
  3. https://exif-worker.glitch.me/without-worker.html पर जाएं.
  4. परफ़ॉर्मेंस पैनल में, DevTools पैनल के ऊपर दाएं कोने में मौजूद रिकॉर्ड करें पर क्लिक करें.
  5. फ़ील्ड में यह इमेज लिंक—या अपनी पसंद की कोई दूसरी इमेज, जिसमें Exif मेटाडेटा शामिल है— चिपकाएं और उस JPEG इमेज पाएं! बटन पर क्लिक करें.
  6. इंटरफ़ेस में Exif मेटाडेटा भर जाने के बाद, रिकॉर्डिंग बंद करने के लिए रिकॉर्ड करें पर फिर से क्लिक करें.
इमेज मेटाडेटा इकट्ठा करने वाले ऐप्लिकेशन की गतिविधि को दिखाने वाला परफ़ॉर्मेंस प्रोफ़ाइलर, पूरी तरह से मुख्य थ्रेड पर हो रहा है. इसमें दो मुख्य काम शामिल हैं. पहला, जो अनुरोध की गई इमेज को फ़ेच करने और उसे डिकोड करने के लिए फ़ेच करता है. दूसरा, जो इमेज से मेटाडेटा निकालता है.
इमेज मेटाडेटा इकट्ठा करने वाले ऐप्लिकेशन में मुख्य थ्रेड की गतिविधि. ध्यान दें कि सभी गतिविधि, मुख्य थ्रेड पर होती है.

ध्यान दें कि हो सकता है कि रास्टराइज़र थ्रेड वगैरह जैसे अन्य थ्रेड के अलावा, ऐप्लिकेशन में मौजूद सभी चीज़ें मुख्य थ्रेड पर होती हैं. मुख्य थ्रेड पर, ये होता है:

  1. यह फ़ॉर्म, इनपुट लेता है और Exif मेटाडेटा वाली इमेज का शुरुआती हिस्सा पाने के लिए fetch अनुरोध भेजता है.
  2. इमेज डेटा को ArrayBuffer में बदल दिया जाता है.
  3. exif-reader स्क्रिप्ट का इस्तेमाल, इमेज से Exif मेटाडेटा निकालने के लिए किया जाता है.
  4. मेटाडेटा को स्क्रैप करके एक एचटीएमएल स्ट्रिंग बनाई जाती है. इसके बाद, यह मेटाडेटा व्यूअर में अपने-आप जानकारी भर जाती है.

अब इसके उलट, एक ही तरह के व्यवहार को लागू करने के साथ-साथ वेब वर्कर का इस्तेमाल करना होगा!

किसी वेब वर्कर के साथ मुख्य थ्रेड कैसा दिखता है

अब आपने देख लिया है कि मुख्य थ्रेड पर JPEG फ़ाइल से Exif मेटाडेटा एक्सट्रैक्ट करने के तरीके कैसे दिखते हैं, तो इस पर नज़र डालें कि किसी वेब वर्कर के शामिल होने पर कैसा दिखता है:

  1. Chrome में एक और टैब खोलें और उसका DevTools खोलें.
  2. परफ़ॉर्मेंस पैनल खोलें.
  3. https://exif-worker.glitch.me/with-worker.html पर जाएं.
  4. परफ़ॉर्मेंस पैनल में, DevTools पैनल के ऊपर दाएं कोने में मौजूद रिकॉर्ड करें बटन पर क्लिक करें.
  5. इस इमेज का लिंक फ़ील्ड में चिपकाएं और वह JPEG पाएं! बटन क्लिक करें.
  6. इंटरफ़ेस में Exif मेटाडेटा भर जाने के बाद, रिकॉर्डिंग बंद करने के लिए, रिकॉर्ड करें बटन पर फिर से क्लिक करें.
परफ़ॉर्मेंस प्रोफ़ाइलर, इमेज मेटाडेटा इकट्ठा करने वाले ऐप्लिकेशन की गतिविधि दिखाता है. यह गतिविधि, मुख्य थ्रेड और वेब वर्कर थ्रेड, दोनों पर हो रही है. मुख्य थ्रेड पर अब भी लंबे टास्क हैं, लेकिन वे काफ़ी छोटे होते हैं. इसके लिए, इमेज को फ़ेच/डिकोड करने और मेटाडेटा निकालने की प्रोसेस पूरी तरह से वेब वर्कर थ्रेड पर होती है. सिर्फ़ मुख्य थ्रेड के काम में वेब वर्कर को और उससे डेटा पास करना शामिल है.
इमेज मेटाडेटा इकट्ठा करने वाले ऐप्लिकेशन में मुख्य थ्रेड की गतिविधि. ध्यान दें कि एक अतिरिक्त वेब वर्कर थ्रेड मौजूद है, जहां ज़्यादातर काम पूरा किया जाता है.

यह वेब वर्कर की ताकत है. मुख्य थ्रेड पर सब कुछ करने के बजाय, मेटाडेटा व्यूअर को एचटीएमएल से अपने-आप भरने के अलावा, बाकी सारा काम एक अलग थ्रेड पर किया जाता है. इसका मतलब है कि मुख्य थ्रेड को अन्य काम करने के लिए खाली किया गया है.

इस ऐप्लिकेशन का सबसे बड़ा फ़ायदा यह है कि वेब वर्कर का इस्तेमाल नहीं करने वाले इस ऐप्लिकेशन के वर्शन से अलग, exif-reader स्क्रिप्ट मुख्य थ्रेड पर लोड नहीं होती, बल्कि वेब वर्कर थ्रेड पर लोड होती है. इसका मतलब है कि exif-reader स्क्रिप्ट को डाउनलोड, पार्स, और कंपाइल करने में लगने वाला खर्च, मुख्य थ्रेड से अलग होता है.

अब वेब वर्कर कोड के बारे में विस्तार से जानें, जिसकी वजह से यह सब संभव हो पाता है!

वेब वर्कर कोड पर एक नज़र

वेब वर्कर के बदलाव को समझना काफ़ी नहीं है. इससे यह समझने में भी मदद मिलती है कि इस मामले में, कोड कैसा दिखता है, जिससे आपको पता चलता है कि वेब वर्कर के दायरे में क्या हो सकता है.

उस मुख्य थ्रेड कोड से शुरू करें जो वेब वर्कर के तस्वीर डालने से पहले होना ज़रूरी है:

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

यह कोड मुख्य थ्रेड पर चलता है और वेब वर्कर को इमेज का यूआरएल भेजने के लिए फ़ॉर्म सेट अप करता है. वहां से, वेब वर्कर कोड 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 का यह बिट, मैसेजिंग पाइपलाइन सेट अप करता है, ताकि जब उपयोगकर्ता किसी JPEG फ़ाइल के यूआरएल के साथ फ़ॉर्म सबमिट करे, तो यूआरएल वेब वर्कर तक पहुंच जाए. इसके बाद, यह अगला कोड JPEG फ़ाइल से Exif मेटाडेटा निकालता है, एक एचटीएमएल स्ट्रिंग बनाता है, और उस एचटीएमएल को 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 कॉल को अलग करना और जवाबों को प्रोसेस करना, मुख्य थ्रेड को ब्लॉक किए बिना बहुत ज़्यादा डेटा प्रोसेस करना. यह सिर्फ़ स्टार्टर के लिए है.

अपने वेब ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाते समय, ऐसे किसी भी काम के बारे में सोचना शुरू करें जिसे वेब वर्कर के लिए सही तरीके से किया जा सकता हो. ये फ़ायदे काफ़ी ज़्यादा हो सकते हैं और इनसे आपकी वेबसाइट पर उपयोगकर्ताओं को बेहतर अनुभव मिल सकता है.