簡體   English   中英

Service Worker 僅顯示第一個推送通知(來自雲消息傳遞),直到我重新加載 - 工作人員收到消息

[英]Service Worker only showing first push notification (from cloud messaging) until I reload - message IS received by the worker

我正在嘗試使用此 Web Push 演練來允許我的客戶將推送通知發送到他們的手機/桌面: https : //framework.realtime.co/demo/web-push/

站點上的演示對我有用,當我將其復制到我的服務器時,我能夠向下推送消息,並且每次向下推送通道時,我都會看到它們被我的服務工作者記錄在 JavaScript 控制台中。

但是,只有在頻道下推的第一個消息會導致出現通知,其余的根本不顯示。 如果我撤銷 service-worker 並重新加載頁面(以獲取新頁面),它會再次運行 - 1 次推送。 在此處輸入圖片說明

我正在使用與它們相同的 ortc.js 文件,一個幾乎相同的 service-worker.js,修改為能夠為圖像/URL 選項傳遞 JSON。 我修改后的服務工作者代碼如下。

我在 JS 控制台中沒有收到任何錯誤(上圖中的 2 來自其他東西),但是我在 service worker 旁邊看到了一個紅色的 x 圖標,盡管它旁邊的數字似乎不是與我能說出的任何事情相關聯(單擊它什么也不做;單擊 service-worker.js 一側只會將我帶到下面的 service-worker.js 文件的第 1 行。 在此處輸入圖片說明

我的問題是:為什么我會收到第一個通知,而不是其他任何通知? 或者我該如何調試它? 我的 JS 控制台正在顯示有效載荷,並且通過斷點單步執行 JS 讓我迷失在縮小的 firebase 代碼中(我已經為 firebase.js 文件嘗試了 3.5 和 6.5)。

這是我的服務人員:

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': '580405122074'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const fb_messaging = firebase.messaging();

// Buffer to save multipart messages
var messagesBuffer = {};

// Gets the number of keys in a dictionary
var countKeys = function (dic) {
  var count = 0;
  for (var i in dic) {
      count++;
  }
  return count;
};

// Parses the Realtime messages using multipart format
var parseRealtimeMessage = function (message) {
  // Multi part
  var regexPattern = /^(\w[^_]*)_{1}(\d*)-{1}(\d*)_{1}([\s\S.]*)$/;
  var match = regexPattern.exec(message);

  var messageId = null;
  var messageCurrentPart = 1;
  var messageTotalPart = 1;
  var lastPart = false;

  if (match && match.length > 0) {
      if (match[1]) {
          messageId = match[1];
      }
      if (match[2]) {
          messageCurrentPart = match[2];
      }
      if (match[3]) {
          messageTotalPart = match[3];
      }
      if (match[4]) {
          message = match[4];
      }
  }

  if (messageId) {
      if (!messagesBuffer[messageId]) {
          messagesBuffer[messageId] = {};
      }
      messagesBuffer[messageId][messageCurrentPart] = message;
      if (countKeys(messagesBuffer[messageId]) == messageTotalPart) {
                lastPart = true;
      }
  }
  else {
      lastPart = true;
  }

  if (lastPart) {
      if (messageId) {
          message = "";

          // Aggregate all parts
          for (var i = 1; i <= messageTotalPart; i++) {
              message += messagesBuffer[messageId][i];
              delete messagesBuffer[messageId][i];
          }

          delete messagesBuffer[messageId];
      }

      return message;
  } else {
    // We don't have yet all parts, we need to wait ...
    return null;
  }
}

// Shows a notification
function showNotification(message, settings) {
  // In this example we are assuming the message is a simple string
  // containing the notification text. The target link of the notification
  // click is fixed, but in your use case you could send a JSON message with
  // a link property and use it in the click_url of the notification

  // The notification title
  var notificationTitle = 'Web Push Notification';
  var title = "Company Name";
  var icon = "/img/default.png";
  var url = "https://www.example.com/";
  var tag = "same";

  if(settings != undefined) {
      if(hasJsonStructure(settings)) settings = JSON.parse(settings);
      title = settings.title;
      icon = settings.icon;
      url = settings.click_url;
      tag = "same";
  }

  // The notification properties
  const notificationOptions = {
    body: message,
    icon: icon,
    data: {
      click_url: url
    },
    tag: tag
  };

  return self.registration.showNotification(title,
      notificationOptions);
}

// If you would like to customize notifications that are received in the
// background (Web app is closed or not in browser focus) then you should
// implement this optional method.
fb_messaging.setBackgroundMessageHandler(function(payload) {
  console.log('Received background message ', payload);

  // Customize notification here
  if(payload.data && payload.data.M) {
    var message = parseRealtimeMessage(payload.data.M);
    return showNotification(message, payload.data.P);
  }
});

// Forces a notification
self.addEventListener('message', function (evt) {
   if(hasJsonStructure(evt.data)) {
       var opts = JSON.parse(evt.data);
       var message = opts.message;
       evt.waitUntil(showNotification(message, opts));
   }
   else evt.waitUntil(showNotification(evt.data));
});

// The user has clicked on the notification ...
self.addEventListener('notificationclick', function(event) {
  // Android doesn’t close the notification when you click on it
  // See: http://crbug.com/463146
  event.notification.close();

  if(event.notification.data && event.notification.data.click_url) {
    // gets the notitication click url
    var click_url = event.notification.data.click_url;

    // This looks to see if the current is already open and
    // focuses if it is
    event.waitUntil(clients.matchAll({
      type: "window"
    }).then(function(clientList) {
      for (var i = 0; i < clientList.length; i++) {
        var client = clientList[i];
        if (client.url == click_url && 'focus' in client)
          return client.focus();
      }
      if (clients.openWindow) {
        var url = click_url;
        return clients.openWindow(url);
      }

    }));
  }
});

function hasJsonStructure(str) {
    if (typeof str !== 'string') return false;
    try {
        const result = JSON.parse(str);
        const type = Object.prototype.toString.call(result);
        return type === '[object Object]'
            || type === '[object Array]';
    } catch (err) {
        return false;
    }
}

我有一個類似的問題。 我正在使用選項對象中的 tag 屬性。 我給出了一個固定值而不是一個唯一值。 所以只出現了第一個通知。 然后我讀了這個:

標簽:給定通知的 ID,允許您在必要時使用腳本查找、替換或刪除通知。

在文檔中並理解原因它需要是一個唯一的值。 所以現在每個通知都出現了。 我如何看待你的標簽變量是硬編碼的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM