कुछ मामलों में, किसी वेब ऐप्लिकेशन को पेज और सर्विस वर्कर के बीच दो-तरफ़ा कम्यूनिकेशन चैनल बनाने की ज़रूरत पड़ सकती है.
उदाहरण के लिए: पॉडकास्ट पीडब्ल्यूए में, उपयोगकर्ता को ऑफ़लाइन सुनने के लिए एपिसोड डाउनलोड करने की सुविधा दी जा सकती है. साथ ही, सर्विस वर्कर को पेज को प्रोग्रेस के बारे में नियमित तौर पर जानकारी देने की अनुमति दी जा सकती है, ताकि मुख्य थ्रेड यूज़र इंटरफ़ेस (यूआई) को अपडेट कर सके.
इस गाइड में, हम Window और सर्विस वर्कर के बीच टू-वे कम्यूनिकेशन लागू करने के अलग-अलग तरीकों के बारे में जानेंगे. इसके लिए, हम अलग-अलग एपीआई, Workbox लाइब्रेरी, और कुछ ऐडवांस मामलों के बारे में जानेंगे.
Workbox का इस्तेमाल करना
workbox-window, Workbox लाइब्रेरी के मॉड्यूल का एक सेट है. इसे विंडो कॉन्टेक्स्ट में चलाने के लिए बनाया गया है. Workbox
क्लास, इंस्टेंस के रजिस्टर किए गए सर्विस वर्कर को मैसेज भेजने और जवाब का इंतज़ार करने के लिए, messageSW() मेथड उपलब्ध कराती है.
पेज का यह कोड, एक नया Workbox इंस्टेंस बनाता है और सर्विस वर्कर को एक मैसेज भेजता है, ताकि उसका वर्शन हासिल किया जा सके:
const wb = new Workbox('/sw.js');
wb.register();
const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);
सर्विस वर्कर, दूसरी ओर एक मैसेज लिसनर लागू करता है और रजिस्टर किए गए सर्विस वर्कर को जवाब देता है:
const SW_VERSION = '1.0.0';
self.addEventListener('message', (event) => {
if (event.data.type === 'GET_VERSION') {
event.ports[0].postMessage(SW_VERSION);
}
});
यह लाइब्रेरी, ब्राउज़र एपीआई का इस्तेमाल करती है. हम अगले सेक्शन में इसकी समीक्षा करेंगे: मैसेज चैनल. हालांकि, यह लागू करने से जुड़ी कई जानकारी को छिपा देता है. इससे इसका इस्तेमाल करना आसान हो जाता है. साथ ही, इस एपीआई के लिए ब्राउज़र के बड़े पैमाने पर मिलने वाले सपोर्ट का फ़ायदा मिलता है.
ब्राउज़र एपीआई का इस्तेमाल करना
अगर Workbox लाइब्रेरी आपकी ज़रूरतों के लिए काफ़ी नहीं है, तो पेजों और सर्विस वर्कर के बीच "टू-वे" कम्यूनिकेशन लागू करने के लिए, कई लोअर-लेवल एपीआई उपलब्ध हैं. इनमें कुछ समानताएं और अंतर हैं:
समानताएं:
- सभी मामलों में, कम्यूनिकेशन की शुरुआत
postMessage()इंटरफ़ेस के ज़रिए होती है. इसके बाद,messageहैंडलर को लागू करके, कम्यूनिकेशन को दूसरे एंड पर रिसीव किया जाता है. - असल में, उपलब्ध सभी एपीआई हमें एक जैसे इस्तेमाल के उदाहरण लागू करने की अनुमति देते हैं. हालांकि, कुछ मामलों में इनमें से कुछ एपीआई, डेवलपमेंट को आसान बना सकते हैं.
अंतर:
- इनके पास, कम्यूनिकेशन के दूसरे पक्ष की पहचान करने के अलग-अलग तरीके होते हैं: इनमें से कुछ, दूसरे कॉन्टेक्स्ट के साफ़ तौर पर दिए गए रेफ़रंस का इस्तेमाल करते हैं. वहीं, कुछ अन्य, हर पक्ष पर इंस्टैंशिएट किए गए प्रॉक्सी ऑब्जेक्ट के ज़रिए, इंप्लिसिट तरीके से कम्यूनिकेट कर सकते हैं.
- इनमें से हर ब्राउज़र के लिए, सहायता का तरीका अलग-अलग होता है.
Broadcast Channel API
ब्रॉडकास्ट चैनल एपीआई, BroadcastChannel ऑब्जेक्ट की मदद से, ब्राउज़िंग कॉन्टेक्स्ट के बीच बुनियादी बातचीत की सुविधा देता है.
इसे लागू करने के लिए, सबसे पहले हर कॉन्टेक्स्ट को एक ही आईडी वाले BroadcastChannel ऑब्जेक्ट को इंस्टैंशिएट करना होगा. साथ ही, उससे मैसेज भेजने और पाने होंगे:
const broadcast = new BroadcastChannel('channel-123');
BroadcastChannel ऑब्जेक्ट, postMessage() इंटरफ़ेस को एक्सपोज़ करता है, ताकि किसी भी लिसनिंग कॉन्टेक्स्ट को मैसेज भेजा जा सके:
//send message
broadcast.postMessage({ type: 'MSG_ID', });
कोई भी ब्राउज़र कॉन्टेक्स्ट, BroadcastChannel ऑब्जेक्ट के onmessage तरीके का इस्तेमाल करके मैसेज सुन सकता है:
//listen to messages
broadcast.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
//process message...
}
};
जैसा कि देखा गया है, किसी खास कॉन्टेक्स्ट का कोई साफ़ रेफ़रंस नहीं है. इसलिए, पहले सर्विस वर्कर या किसी खास क्लाइंट का रेफ़रंस पाने की ज़रूरत नहीं है.
इसका नुकसान यह है कि फ़िलहाल, यह एपीआई Chrome, Firefox, और Edge पर काम करता है. हालांकि, Safari जैसे अन्य ब्राउज़र पर यह अब भी काम नहीं करता.
Client API
क्लाइंट एपीआई की मदद से, उन सभी WindowClient ऑब्जेक्ट का रेफ़रंस पाया जा सकता है जो सर्विस वर्कर के कंट्रोल में मौजूद ऐक्टिव टैब को दिखाते हैं.
पेज को एक ही सर्विस वर्कर कंट्रोल करता है. इसलिए, यह serviceWorker इंटरफ़ेस के ज़रिए, सीधे तौर पर ऐक्टिव सर्विस वर्कर को मैसेज भेजता है और उससे मैसेज पाता है:
//send message
navigator.serviceWorker.controller.postMessage({
type: 'MSG_ID',
});
//listen to messages
navigator.serviceWorker.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
//process response
}
};
इसी तरह, सर्विस वर्कर onmessage लिसनर को लागू करके मैसेज सुनता है:
//listen to messages
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'MSG_ID') {
//Process message
}
});
अपने किसी भी क्लाइंट से वापस संपर्क करने के लिए, सर्विस वर्कर WindowClient ऑब्जेक्ट का कलेक्शन हासिल करता है. इसके लिए, वह Clients.matchAll() और Clients.get() जैसे तरीके इस्तेमाल करता है. इसके बाद, यह इनमें से किसी भी विकल्प को postMessage() कर सकता है:
//Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
if (clients && clients.length) {
//Respond to last focused tab
clients[0].postMessage({type: 'MSG_ID'});
}
});
Client API, सर्विस वर्कर से सभी ऐक्टिव टैब के साथ आसानी से कम्यूनिकेट करने का एक अच्छा विकल्प है. यह एपीआई, सभी मुख्य ब्राउज़र पर काम करता है. हालांकि, हो सकता है कि इसके सभी तरीके उपलब्ध न हों. इसलिए, अपनी साइट पर इसे लागू करने से पहले, यह पक्का कर लें कि यह ब्राउज़र पर काम करता हो.
मैसेज चैनल
Message Channel के लिए, एक कॉन्टेक्स्ट से दूसरे कॉन्टेक्स्ट में पोर्ट को तय करना और पास करना ज़रूरी है. इससे दो-तरफ़ा कम्यूनिकेशन चैनल सेट अप किया जा सकता है.
चैनल को शुरू करने के लिए, पेज MessageChannel ऑब्जेक्ट को इंस्टैंशिएट करता है. साथ ही, रजिस्टर किए गए सर्विस वर्कर को पोर्ट भेजने के लिए, इसका इस्तेमाल करता है. पेज पर onmessage लिसनर भी लागू किया जाता है, ताकि दूसरे कॉन्टेक्स्ट से मैसेज मिल सकें:
const messageChannel = new MessageChannel();
//Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
messageChannel.port2,
]);
//Listen to messages
messageChannel.port1.onmessage = (event) => {
// Process message
};
सर्विस वर्कर को पोर्ट मिलता है, वह उसका रेफ़रंस सेव करता है, और उसका इस्तेमाल करके दूसरी तरफ़ मैसेज भेजता है:
let communicationPort;
//Save reference to port
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PORT_INITIALIZATION') {
communicationPort = event.ports[0];
}
});
//Send messages
communicationPort.postMessage({type: 'MSG_ID'});
फ़िलहाल, MessageChannel का इस्तेमाल सभी मुख्य ब्राउज़र पर किया जा सकता है.
ऐडवांस एपीआई: बैकग्राउंड सिंक और बैकग्राउंड फ़ेच
इस गाइड में, हमने दोतरफ़ा कम्यूनिकेशन की तकनीकों को लागू करने के तरीकों के बारे में जाना. ये तरीके, आसान मामलों के लिए हैं. जैसे, किसी कार्रवाई के बारे में बताने वाला स्ट्रिंग मैसेज पास करना या एक कॉन्टेक्स्ट से दूसरे कॉन्टेक्स्ट में कैश मेमोरी में सेव करने के लिए, यूआरएल की सूची पास करना. इस सेक्शन में, हम दो एपीआई के बारे में जानेंगे. इनकी मदद से, कुछ खास स्थितियों को मैनेज किया जा सकता है. जैसे, इंटरनेट कनेक्टिविटी न होना और डाउनलोड होने में ज़्यादा समय लगना.
बैकग्राउंड सिंक
कोई चैट ऐप्लिकेशन यह पक्का करना चाहता है कि खराब कनेक्टिविटी की वजह से मैसेज कभी न खोएं. बैकग्राउंड सिंक एपीआई की मदद से, उन कार्रवाइयों को बाद में फिर से करने के लिए रोका जा सकता है जिन्हें उपयोगकर्ता के पास स्टेबल कनेक्टिविटी होने पर किया जाना है. यह पक्का करने के लिए कि उपयोगकर्ता जो भी भेजना चाहता है वह वाकई भेजा गया है, यह तरीका काम का है.
postMessage() इंटरफ़ेस के बजाय, पेज sync को रजिस्टर करता है:
navigator.serviceWorker.ready.then(function (swRegistration) {
return swRegistration.sync.register('myFirstSync');
});
इसके बाद, सर्विस वर्कर मैसेज को प्रोसेस करने के लिए, sync इवेंट को सुनता है:
self.addEventListener('sync', function (event) {
if (event.tag == 'myFirstSync') {
event.waitUntil(doSomeStuff());
}
});
doSomeStuff() फ़ंक्शन को एक प्रॉमिस दिखाना चाहिए, जिससे पता चले कि वह जो करने की कोशिश कर रहा है उसमें सफल हुआ या नहीं. अगर प्रॉमिस पूरा हो जाता है, तो सिंक की प्रोसेस पूरी हो जाती है. अगर यह सिंक नहीं हो पाता है, तो फिर से कोशिश करने के लिए, एक और सिंक शेड्यूल किया जाएगा. सिंक करने की प्रोसेस को फिर से शुरू करने के लिए, कनेक्टिविटी का इंतज़ार किया जाता है. साथ ही, एक्स्पोनेंशियल बैक-ऑफ़ का इस्तेमाल किया जाता है.
ऑपरेशन पूरा होने के बाद, सर्विस वर्कर पेज के साथ फिर से कम्यूनिकेट कर सकता है, ताकि यूज़र इंटरफ़ेस (यूआई) को अपडेट किया जा सके. इसके लिए, पहले से एक्सप्लोर किए गए किसी भी कम्यूनिकेशन एपीआई का इस्तेमाल किया जा सकता है.
Google Search, बैकग्राउंड सिंक का इस्तेमाल करके, खराब कनेक्टिविटी की वजह से पूरी न हो पाई क्वेरी को सेव रखता है. साथ ही, उपयोगकर्ता के ऑनलाइन होने पर उन्हें फिर से आज़माता है. कार्रवाई पूरी होने के बाद, वे वेब ऐप्लिकेशन से भेजे गए पुश नोटिफ़िकेशन के ज़रिए उपयोगकर्ता को नतीजे की जानकारी देते हैं:
बैकग्राउंड फ़ेच
मैसेज भेजने या कैश मेमोरी में सेव करने के लिए यूआरएल की सूची जैसे छोटे कामों के लिए, अब तक बताए गए विकल्प अच्छे हैं. अगर टास्क पूरा होने में ज़्यादा समय लगता है, तो ब्राउज़र सर्विस वर्कर को बंद कर देगा. ऐसा न करने पर, उपयोगकर्ता की निजता और बैटरी को खतरा हो सकता है.
Background Fetch API की मदद से, ज़्यादा समय लेने वाले काम को सर्विस वर्कर को ऑफ़लोड किया जा सकता है. जैसे, फ़िल्में, पॉडकास्ट या गेम के लेवल डाउनलोड करना.
पेज से सर्विस वर्कर के साथ इंटरैक्ट करने के लिए, postMessage() के बजाय backgroundFetch.fetch का इस्तेमाल करें:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.fetch(
'my-fetch',
['/ep-5.mp3', 'ep-5-artwork.jpg'],
{
title: 'Episode 5: Interesting things.',
icons: [
{
sizes: '300x300',
src: '/ep-5-icon.png',
type: 'image/png',
},
],
downloadTotal: 60 * 1024 * 1024,
},
);
});
BackgroundFetchRegistration ऑब्जेक्ट की मदद से, पेज progress इवेंट को सुन सकता है, ताकि डाउनलोड की प्रोग्रेस को ट्रैक किया जा सके:
bgFetch.addEventListener('progress', () => {
// If we didn't provide a total, we can't provide a %.
if (!bgFetch.downloadTotal) return;
const percent = Math.round(
(bgFetch.downloaded / bgFetch.downloadTotal) * 100,
);
console.log(`Download progress: ${percent}%`);
});
अगले चरण
इस गाइड में, हमने पेज और सर्विस वर्कर के बीच कम्यूनिकेशन के सबसे सामान्य मामले (दोनों तरफ़ से होने वाला कम्यूनिकेशन) के बारे में जाना.
कई बार, किसी व्यक्ति को दूसरे व्यक्ति से बातचीत करने के लिए सिर्फ़ एक कॉन्टेक्स्ट की ज़रूरत होती है. इसके लिए, उसे जवाब पाने की ज़रूरत नहीं होती. अपने पेजों पर, सर्विस वर्कर से और सर्विस वर्कर तक यूनिडायरेक्शनल तकनीक लागू करने के तरीके के बारे में जानने के लिए, यहां दी गई गाइड देखें. इनमें इस्तेमाल के उदाहरण और प्रोडक्शन के उदाहरण भी शामिल हैं:
- इंपेरेटिव कैशिंग गाइड: संसाधनों को पहले से कैश मेमोरी में सेव करने के लिए, पेज से किसी सर्विस वर्कर को कॉल करना. उदाहरण के लिए, प्रीफ़ेच करने की स्थितियों में.
- अपडेट ब्रॉडकास्ट करना: अहम अपडेट के बारे में जानकारी देने के लिए, सर्विस वर्कर से पेज को कॉल करना. जैसे, वेब ऐप्लिकेशन का नया वर्शन उपलब्ध है.