सामान्य सूचना पैटर्न

हम वेब पुश के लिए, उन्हें लागू करने के कुछ सामान्य पैटर्न देखने जा रहे हैं.

इसके लिए, आपको सेवा वर्कर में उपलब्ध कुछ अलग-अलग एपीआई का इस्तेमाल करना होगा.

सूचना बंद होने का इवेंट

पिछले सेक्शन में, हमने notificationclick इवेंट को सुनने का तरीका देखा था.

एक notificationclose इवेंट भी हो सकता है, जिसे तब कॉल किया जाता है, जब उपयोगकर्ता आपकी किसी सूचना को खारिज कर देता है (यानी सूचना पर क्लिक करने के बजाय, उपयोगकर्ता उस सूचना पर क्लिक करने के बजाय, उस पर क्लिक करता है या उसे बाहर की ओर स्वाइप करता है).

आम तौर पर, इस इवेंट का इस्तेमाल आंकड़ों के लिए किया जाता है, ताकि सूचनाओं के साथ उपयोगकर्ता की दिलचस्पी को ट्रैक किया जा सके.

self.addEventListener('notificationclose', function (event) {
  const dismissedNotification = event.notification;

  const promiseChain = notificationCloseAnalytics();
  event.waitUntil(promiseChain);
});

सूचना में डेटा जोड़ना

पुश मैसेज मिलने पर, आम तौर पर ऐसा डेटा मिलता है जो सिर्फ़ तब काम का होता है, जब उपयोगकर्ता ने सूचना पर क्लिक किया हो. उदाहरण के लिए, वह यूआरएल जिस पर सूचना पर क्लिक करने पर जाना चाहिए.

किसी पुश इवेंट से डेटा लेने और उसे किसी सूचना में जोड़ने का सबसे आसान तरीका यह है कि showNotification() में पास किए गए विकल्प ऑब्जेक्ट में data पैरामीटर जोड़ें, जैसे:

const options = {
  body:
    'This notification has data attached to it that is printed ' +
    "to the console when it's clicked.",
  tag: 'data-notification',
  data: {
    time: new Date(Date.now()).toString(),
    message: 'Hello, World!',
  },
};
registration.showNotification('Notification with Data', options);

क्लिक हैंडलर में, डेटा को event.notification.data से ऐक्सेस किया जा सकता है.

const notificationData = event.notification.data;
console.log('');
console.log('The notification data has the following parameters:');
Object.keys(notificationData).forEach((key) => {
  console.log(`  ${key}: ${notificationData[key]}`);
});
console.log('');

विंडो खोलना

किसी सूचना का जवाब देने के लिए, आम तौर पर किसी खास यूआरएल की विंडो / टैब खोला जाता है. हम ऐसा clients.openWindow() एपीआई की मदद से कर सकते हैं.

अपने notificationclick इवेंट में, हम कुछ ऐसा कोड चलाएंगे:

const examplePage = '/demos/notification-examples/example-page.html';
const promiseChain = clients.openWindow(examplePage);
event.waitUntil(promiseChain);

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

मौजूदा विंडो पर फ़ोकस करें

जब भी उपयोगकर्ता किसी सूचना पर क्लिक करता है, तो हम एक नई विंडो खोलने के बजाय, किसी विंडो पर फ़ोकस करना चाहिए.

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

पिछले उदाहरण को ध्यान में रखते हुए, हम कोड में बदलाव करेंगे, ताकि यह देखा जा सके कि /demos/notification-examples/example-page.html पहले से खुला है या नहीं.

const urlToOpen = new URL(examplePage, self.location.origin).href;

const promiseChain = clients
  .matchAll({
    type: 'window',
    includeUncontrolled: true,
  })
  .then((windowClients) => {
    let matchingClient = null;

    for (let i = 0; i < windowClients.length; i++) {
      const windowClient = windowClients[i];
      if (windowClient.url === urlToOpen) {
        matchingClient = windowClient;
        break;
      }
    }

    if (matchingClient) {
      return matchingClient.focus();
    } else {
      return clients.openWindow(urlToOpen);
    }
  });

event.waitUntil(promiseChain);

आइए, कोड को सिलसिलेवार तरीके से देखते हैं.

सबसे पहले, हम यूआरएल एपीआई का इस्तेमाल करके, अपने उदाहरण वाले पेज को पार्स करते हैं. यह एक शानदार तरकीब है जो मैंने जेफ़ पॉसनिक से उठाई है. location ऑब्जेक्ट के साथ new URL() को कॉल करने पर, अगर दी गई स्ट्रिंग रिलेटिव है, तो एक पूर्ण यूआरएल दिखेगा. इसका मतलब है कि /, https://example.com/ हो जाएगा.

हम यूआरएल को एब्सोलूट बनाते हैं, ताकि हम बाद में इसे विंडो के यूआरएल से मैच कर सकें.

const urlToOpen = new URL(examplePage, self.location.origin).href;

इसके बाद, हमें WindowClient ऑब्जेक्ट की सूची मिलती है. यह सूची, फ़िलहाल खुले टैब और विंडो की होती है. (ध्यान रखें कि ये टैब सिर्फ़ आपके ऑरिजिन के लिए हैं.)

const promiseChain = clients.matchAll({
  type: 'window',
  includeUncontrolled: true,
});

matchAll में दिए गए विकल्पों से ब्राउज़र को पता चलता है कि हमें सिर्फ़ "विंडो" टाइप के क्लाइंट खोजने हैं. इसका मतलब है कि सिर्फ़ टैब और विंडो खोजें और वेब वर्कर्स को बाहर रखें. includeUncontrolled की मदद से, हम आपके ऑरिजिन के उन सभी टैब को खोज सकते हैं जिन्हें मौजूदा सर्विस वर्कर कंट्रोल नहीं करता. इसका मतलब है कि इस कोड को चलाने वाला सर्विस वर्कर. आम तौर पर, matchAll() को कॉल करते समय, आपको हमेशा includeUncontrolled को सही रखना होगा.

हम दिखाए गए वाद को promiseChain के तौर पर कैप्चर करते हैं, ताकि बाद में हम उसे event.waitUntil() में भेज सकें, ताकि हमारे सर्विस वर्कर ऐक्टिव रहें.

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

अगर हमें मैच होने वाला कोई क्लाइंट नहीं मिलता है, तो हम पिछले सेक्शन की तरह ही एक नई विंडो खोलते हैं.

.then((windowClients) => {
  let matchingClient = null;

  for (let i = 0; i < windowClients.length; i++) {
    const windowClient = windowClients[i];
    if (windowClient.url === urlToOpen) {
      matchingClient = windowClient;
      break;
    }
  }

  if (matchingClient) {
    return matchingClient.focus();
  } else {
    return clients.openWindow(urlToOpen);
  }
});

सूचनाओं को मर्ज करना

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

हालांकि, Notification API का इस्तेमाल करके सूचनाओं को छोटा किया जा सकता है. किसी चैट ऐप्लिकेशन के बारे में सोचें. हो सकता है कि डेवलपर, नई सूचना में सिर्फ़ नया मैसेज दिखाने के बजाय, "आपके पास मैट से दो मैसेज हैं" जैसा मैसेज दिखाना चाहे.

ऐसा करने के लिए, registration.getNotifications() API का इस्तेमाल करें. इससे आपको अपने वेब ऐप्लिकेशन के लिए, फ़िलहाल दिख रही सभी सूचनाओं का ऐक्सेस मिलता है. इसके अलावा, मौजूदा सूचनाओं में अन्य तरीकों से भी बदलाव किया जा सकता है.

आइए, चैट के उदाहरण को लागू करने के लिए, इस एपीआई का इस्तेमाल करने का तरीका देखें.

हमारे चैट ऐप्लिकेशन में, मान लेते हैं कि हर सूचना में कुछ डेटा है और उसमें उपयोगकर्ता नाम भी शामिल है.

सबसे पहले, हम किसी खास उपयोगकर्ता नाम वाले उपयोगकर्ता के लिए, खुली सूचनाएं ढूंढना चाहेंगे. हमें registration.getNotifications() मिलेगा और हम उन पर लूप करेंगे और किसी खास उपयोगकर्ता नाम के लिए notification.data की जांच करेंगे:

const promiseChain = registration.getNotifications().then((notifications) => {
  let currentNotification;

  for (let i = 0; i < notifications.length; i++) {
    if (notifications[i].data && notifications[i].data.userName === userName) {
      currentNotification = notifications[i];
    }
  }

  return currentNotification;
});

इसके बाद, इस सूचना को नई सूचना से बदलें.

इस फ़र्ज़ी मैसेज ऐप्लिकेशन में, हम नए मैसेज की संख्या को ट्रैक करेंगे. इसके लिए, हम अपनी नई सूचना के डेटा में एक संख्या जोड़ेंगे और हर नई सूचना के साथ इस संख्या को बढ़ाएंगे.

.then((currentNotification) => {
  let notificationTitle;
  const options = {
    icon: userIcon,
  }

  if (currentNotification) {
    // We have an open notification, let's do something with it.
    const messageCount = currentNotification.data.newMessageCount + 1;

    options.body = `You have ${messageCount} new messages from ${userName}.`;
    options.data = {
      userName: userName,
      newMessageCount: messageCount
    };
    notificationTitle = `New Messages from ${userName}`;

    // Remember to close the old notification.
    currentNotification.close();
  } else {
    options.body = `"${userMessage}"`;
    options.data = {
      userName: userName,
      newMessageCount: 1
    };
    notificationTitle = `New Message from ${userName}`;
  }

  return registration.showNotification(
    notificationTitle,
    options
  );
});

अगर फ़िलहाल कोई सूचना दिख रही है, तो हम मैसेज की संख्या बढ़ा देते हैं और सूचना का टाइटल और मुख्य हिस्सा तय करते हैं. अगर कोई सूचना नहीं है, तो हम 1 में से newMessageCount के साथ नई सूचना बनाते हैं.

इससे पहला मैसेज कुछ ऐसा दिखेगा:

मर्ज किए बिना पहली सूचना.

दूसरी सूचना मिलने पर, सूचनाएं इस तरह दिखेंगी:

मर्ज करने के बाद मिली दूसरी सूचना.

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

नियम का अपवाद

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

अपने पुश इवेंट में, विंडो क्लाइंट की जांच करके और फ़ोकस की गई विंडो ढूंढकर, यह देखा जा सकता है कि आपको कोई सूचना दिखानी है या नहीं.

सभी विंडो पाने और फ़ोकस की गई विंडो ढूंढने का कोड ऐसा दिखता है:

function isClientFocused() {
  return clients
    .matchAll({
      type: 'window',
      includeUncontrolled: true,
    })
    .then((windowClients) => {
      let clientIsFocused = false;

      for (let i = 0; i < windowClients.length; i++) {
        const windowClient = windowClients[i];
        if (windowClient.focused) {
          clientIsFocused = true;
          break;
        }
      }

      return clientIsFocused;
    });
}

हम अपने सभी विंडो क्लाइंट पाने के लिए, clients.matchAll() का इस्तेमाल करते हैं. इसके बाद, हम focused पैरामीटर की जांच करके, उन पर लूप लगाते हैं.

हम अपने पुश इवेंट में इस फ़ंक्शन का इस्तेमाल करके यह तय करेंगे कि हमें कोई सूचना दिखानी है या नहीं:

const promiseChain = isClientFocused().then((clientIsFocused) => {
  if (clientIsFocused) {
    console.log("Don't need to show a notification.");
    return;
  }

  // Client isn't focused, we need to show a notification.
  return self.registration.showNotification('Had to show a notification.');
});

event.waitUntil(promiseChain);

किसी पुश इवेंट से किसी पेज को मैसेज भेजना

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

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

मान लें कि हमें एक पुश मिला, और इस बात की जांच की कि हमारा वेब ऐप्लिकेशन अभी फ़ोकस में है, फिर हम हर खुले हुए पेज पर "एक मैसेज पोस्ट" कर सकते हैं, जैसे:

const promiseChain = isClientFocused().then((clientIsFocused) => {
  if (clientIsFocused) {
    windowClients.forEach((windowClient) => {
      windowClient.postMessage({
        message: 'Received a push message.',
        time: new Date().toString(),
      });
    });
  } else {
    return self.registration.showNotification('No focused windows', {
      body: 'Had to show a notification instead of messaging each page.',
    });
  }
});

event.waitUntil(promiseChain);

हम हर पेज पर, मैसेज इवेंट के लिसनर को जोड़कर मैसेज सुनते हैं:

navigator.serviceWorker.addEventListener('message', function (event) {
  console.log('Received a message from service worker: ', event.data);
});

इस मैसेज लिसनर में, अपनी पसंद के मुताबिक कुछ भी किया जा सकता है. जैसे, अपने पेज पर कस्टम यूज़र इंटरफ़ेस (यूआई) दिखाना या मैसेज को पूरी तरह से अनदेखा करना.

यह बात भी ध्यान में रखें कि अगर आप अपने वेब पेज में मैसेज लिसनर को परिभाषित नहीं करते हैं, तो सर्विस वर्कर के मैसेज कुछ भी नहीं करेंगे.

पेज को कैश मेमोरी में सेव करना और विंडो खोलना

इस गाइड में एक स्थिति के बारे में नहीं बताया गया है, लेकिन इस पर चर्चा करना ज़रूरी है. इस स्थिति में, वेब पेजों को कैश मेमोरी में सेव करके, अपने वेब ऐप्लिकेशन के यूज़र एक्सपीरियंस को बेहतर बनाया जा सकता है. ऐसा उन वेब पेजों के लिए किया जा सकता है जिन पर आपके हिसाब से, उपयोगकर्ता आपकी सूचना पर क्लिक करने के बाद जाएंगे.

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

ब्राउज़र के साथ काम करना

notificationclose इवेंट

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 50.
  • Edge: 17.
  • Firefox: 44.
  • Safari: 16.

सोर्स

Clients.openWindow()

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 40.
  • Edge: 17.
  • Firefox: 44.
  • Safari: 11.1.

सोर्स

ServiceWorkerRegistration.getNotifications()

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 40.
  • एज: 17.
  • Firefox: 44.
  • Safari: 16.

सोर्स

clients.matchAll()

ब्राउज़र सहायता

  • Chrome: 42.
  • एज: 17.
  • Firefox: 54.
  • Safari: 11.1.

सोर्स

ज़्यादा जानकारी के लिए, सेवा वर्कर के बारे में जानकारी देने वाली यह पोस्ट देखें.

आगे क्या करना है

कोड लैब