javascript - 如何从 FCM 后台推送通知接收数据到主 javascript 线程,以便这些值可以用于编码?

标签 javascript firebase push-notification firebase-cloud-messaging messaging

我正在开发一个应用程序,我们尝试使用静默 FCM 推送消息从服务器获取少量数据。 FCM 与其前台/后台接收推送通知策略配合良好。我已经从 .js 文件注册了 serviceWorker 并在那里进行了相同的配置,以便我可以在该文件中接收推送通知数据(前台策略)。

当应用程序失去焦点时就会出现问题。主线程不再存在,直到应用程序再次获得焦点,serviceWorker 仍在运行并接收消息,但现在我无法将该数据接收到主线程。

所以我想知道是否有任何方法可以在这些数据集中后将其返回到主线程。

index.js 文件中的主线程代码

if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("./firebase-messaging-sw.js")
      .then((registration) => {
        firebase.initializeApp(firebaseConfig);
        firebase.analytics();
        console.log(registration, "serviceWorker registered!");
        const messaging = firebase.messaging();
        // messaging.useServiceWorker(registration);
        messaging.onMessage((payload) => {
          console.log("[index.js] Foreground Message received.", payload);
          const notificationTitle = payload.notification.title;
          const notificationOptions = {
            body: payload.notification.body,
            icon: payload.notification.icon,
            imgae: payload.notification.image ? payload.notification.image : "",
            click_action: payload.notification.click_action
              ? payload.notification.click_action
              : "",
          };
          let notification = registration.showNotification(
            notificationTitle,
            notificationOptions
          );
          console.log(notification, "notification");
          // const { id, status, file_url } = payload.data;
          // Store.dispatch(MODIFY_REPORT_STATUS(id, status, file_url));
        });

        messaging
          .getToken({ vapidKey: firebaseConfig.vapIdKey })
          .then((currentToken) => {
            if (currentToken) {
              localStorage.setItem("firebaseToken", currentToken);
            } else {
              localStorage.removeItem("firebaseToken", currentToken);
              console.warn(
                "No registration token available. Request permission to generate one."
              );
            }
          })
          .catch((err) => {
            localStorage.removeItem("firebaseToken", currentToken);
            console.error("An error occurred while retrieving token. ", err);
          });
      });
  });
}

这是 firebase-messaging-sw.js 的代码

// Import and configure the Firebase SDK
// These scripts are made available when the app is served or deployed on Firebase Hosting
// If you do not serve/host your project using Firebase Hosting see https://firebase.google.com/docs/web/setup
importScripts("https://www.gstatic.com/firebasejs/8.1.1/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.1.1/firebase-messaging.js");
// importScripts('/__/firebase/init.js');

// const messaging = firebase.messaging();

/**
 * Here is is the code snippet to initialize Firebase Messaging in the Service
 * Worker when your app is not hosted on Firebase Hosting.

 // [START initialize_firebase_in_sw]
 // 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/8.0.1/firebase-app.js');
 importScripts('https://www.gstatic.com/firebasejs/8.0.1/firebase-messaging.js');

 // Initialize the Firebase app in the service worker by passing in
 // your app's Firebase config object.
 // https://firebase.google.com/docs/web/setup#config-object
 firebase.initializeApp({
   apiKey: 'api-key',
   authDomain: 'project-id.firebaseapp.com',
   databaseURL: 'https://project-id.firebaseio.com',
   projectId: 'project-id',
   storageBucket: 'project-id.appspot.com',
   messagingSenderId: 'sender-id',
   appId: 'app-id',
   measurementId: 'G-measurement-id',
 });

 // Retrieve an instance of Firebase Messaging so that it can handle background
 // messages.
 const messaging = firebase.messaging();
 // [END initialize_firebase_in_sw]
 **/
let click_action = "";
self.addEventListener("push", function (event) {
  console.log("PUSH")
  let dt = event.data.json();
  click_action = event.data.json().notification.click_action
    ? event.data.json().notification.click_action
    : "";
  console.log(click_action, "redirect url");
});

self.addEventListener("notificationclick", function (event) {
  // console.log("Notification clicked!!", event.notifiation);
  var redirect_url = event.notification.click_action;
  event.notification.close();
  event.waitUntil(
    clients
      .matchAll({
        type: "window",
      })
      .then(function (clientList) {
        // console.log(clientList);
        for (var i = 0; i < clientList.length; i++) {
          var client = clientList[i];
          if (client.url === "/" && "focus" in client) {
            return client.focus();
          }
        }
        if (clients.openWindow) {
          return clients.openWindow(click_action);
        }
      })
  );
});

firebase.initializeApp({
  apiKey: "AIzaSyCNcY1KYtQExip4Q2jQwYCDGt5y9NbbPoU",
  authDomain: "hot-foods-2020.firebaseapp.com",
  databaseURL: "https://hot-foods-2020.firebaseio.com",
  projectId: "hot-foods-2020",
  storageBucket: "hot-foods-2020.appspot.com",
  messagingSenderId: "749796496166",
  appId: "1:749796496166:web:379830a07371c9d5d6a7e7",
  measurementId: "G-8L15G3BGP8",
});
const messaging = firebase.messaging();
console.log("messaging from firebase-messaging-sw.js ", messaging);
// 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.
// [START on_background_message]
messaging.onBackgroundMessage(function (payload) {

  console.log(
    "[firebase-messaging-sw.js] Received background message ",
    payload, clients
  );
  // Customize notification here
  const notificationTitle = "Background Message Title";
  const notificationOptions = {
    body: "Background Message body.",
    icon: "/firebase-logo.png",
  };

  self.registration.showNotification(notificationTitle, notificationOptions);
});
// [END on_background_message]

最佳答案

不知道你有没有解决办法。我也遇到了同样的问题。我通过使用 client.postMessage 解决了这个问题。 在 firebase-messaging-sw.js 中我添加了以下内容:

messaging.onBackgroundMessage(function(payload) {
    const promiseChain = self.clients
            .matchAll({
        type: "window",
        includeUncontrolled: true,
    })
            .then((windowClients) => {
                for (let i = 0; i < windowClients.length; i++) {
                const windowClient = windowClients[i];
                windowClient.postMessage(payload);
            }
            })
    .then(() => {
        return self.registration.showNotification("mynotification title ");
    });
    return promiseChain;
});

在 App.js 中,我添加了下一个监听器:

navigator.serviceWorker.addEventListener('message', event => {
    // Add handler here
});

关于javascript - 如何从 FCM 后台推送通知接收数据到主 javascript 线程,以便这些值可以用于编码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65330450/

相关文章:

javascript - 在 Fabric.js 中用鼠标旋转东西的正确方法

javascript - 在 eselect 下拉菜单更改上调用 ajax 函数

ios - Cordova :GoogleService-info.plist 的问题

angular - 如何从 Firebase 检索数据以传递到 angularfire2/version-5 中的数组

javascript - 用于在网站上发布并将推送发送到移动设备的表单

javascript - 用于监听我自己的网络服务的推送通知的 Cordova 插件

javascript - 简单的篮球运动 Javascript

javascript - 尝试初始化 Cloud Firestore 时,firebase.firestore() 不是函数

javascript - Chrome 将 Notification.requestPermission() 的结果 'default' 视为 'denied'

javascript - 如何为每个 jquery 同级创建添加/子值的单击事件