即使发送消息后,Firebase 云消息传递 onMessage 也不会在 React 应用程序中触发

agr*_*kid 6 firebase reactjs firebase-cloud-messaging create-react-app

我正在我的 React 应用程序中测试 Firebase Cloud Messaging 功能,该功能是通过 create-react-app 引导的。请注意,我已经正确初始化了 firebase(包括服务器端的 admin SDK),并且我的客户端部署在 https 上。到目前为止我所做的是:

  1. 在 firebase.js 中初始化 firebase 消息传递,并请求通知权限并监听 onMessage 事件
const messaging = firebase.messaging();
messaging
  .requestPermission()
  .then(() => {
    console.log("Permission granted!");
  })
  .catch(() => {
    console.log("Permission denied!");
  });

messaging.onMessage(payload => {
  console.log("onMessage: ", payload);
});
Run Code Online (Sandbox Code Playgroud)
  1. 在公共目录中创建服务工作者文件 firebase-messaging-sw.js
importScripts("https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js");

var config = {
  messagingSenderId: <messageID hidden>
};
firebase.initializeApp(config);

const messaging = firebase.messaging();

Run Code Online (Sandbox Code Playgroud)
  1. 我从另一篇 Stackoverflow 帖子中读到,在 create-react-app 帖子中,这也有必要包含在 index.js 中
if ("serviceWorker" in navigator) {
  navigator.serviceWorker
    .register("../firebase-messaging-sw.js")
    .then(function(registration) {
      console.log("Registration successful, scope is:", registration.scope);
    })
    .catch(function(err) {
      console.log("Service worker registration failed, error:", err);
    });
}
Run Code Online (Sandbox Code Playgroud)
  1. 为了轻松测试消息传递,我在 Main.js 中添加了一个按钮,单击该按钮会将令牌发送到我的服务器(然后服务器将继续发送消息)
const handlePushButtonClick = () => {
    messaging.getToken().then(token => {
      axios.post(<Server link hidden>, {
        token
      });
    });
  };
Run Code Online (Sandbox Code Playgroud)
  1. 然后我在我的快递服务器中设置必要的路线,如下所示
app.post("/api/push", async (req, res) => {
    const registrationToken = req.body.token;
    var message = {
      data: {
        score: "850",
        time: "2:45"
      },
      token: registrationToken
    };
    fb.admin
      .messaging()
      .send(message)
      .then(response => {
        console.log("Successfully sent message:", response);
        res.sendStatus(200);
      })
      .catch(error => {
        console.log("Error sending message:", error);
      });
  });
Run Code Online (Sandbox Code Playgroud)

问题是,我已经验证我的服务器已成功接收令牌,并且实际上已成功发送消息,但在我的客户端,我根本没有收到 onMessage 有效负载对象。

回想一下我的代码,我期望在客户端开发控制台上收到的是包含 onMessage 和有效负载的 console.log。

messaging.onMessage(payload => {
  console.log("onMessage: ", payload);
});
Run Code Online (Sandbox Code Playgroud)

Mah*_*rus 5

解决此问题的简单方法是将Firebse更新到最新版本。

例如。

importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');
Run Code Online (Sandbox Code Playgroud)

注意:更新 Firebase 库版本后, messagingSenderId将无法在您的firebase-messaging-sw.js文件中工作。您必须提供所有其他参数,例如。apiKeyprojectIdappId以及messagesSenderId

例如。

在您的firebase-messaging-sw.js中替换它

firebase.initializeApp({
    messagingSenderId: "Sender ID"
});
Run Code Online (Sandbox Code Playgroud)

有了这个

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",
});
Run Code Online (Sandbox Code Playgroud)
  • 如果还是不行。清理浏览器缓存并重新注册 Service Worker。

  • @andreszs如果您将firebase sdk更新到最新版本(firebasejs/7.8.0/firebase-app.js'&firebasejs/7.8.0/firebase-messaging.js)。它会告诉你错误。SW 中缺少项目 ID 类型。要解决这个问题,您需要添加其余的详细信息。并且它已经过测试。 (2认同)

agr*_*kid 0

我已经认识到自己的错误了。我最初遵循本指南: https: //firebase.google.com/docs/cloud-messaging/js/topic-messaging。当我按照教程进行操作时,我之前并不太清楚我的错误,但这可能是因为我对通知和推送 Web API 非常不熟悉。

本教程的消息对象内部有一个数据对象:

var message = {
  data: {
    score: '850',
    time: '2:45'
  },
  token: registrationToken
};
Run Code Online (Sandbox Code Playgroud)

事实证明,如果我想在消息中发送数据有效负载,我需要在我的 firebase-messaging-sw.js 中包含这堆代码(这部分没有在我链接的教程中显示):

messaging.setBackgroundMessageHandler(payload => {
  const title = payload.data.title;
  const options = {
    body: payload.data.score
  };
  return self.registration.showNotification(title, options);
});
Run Code Online (Sandbox Code Playgroud)

请注意,仅当您想要发送数据有效负载(此后您可以在 Service Worker 文件中灵活操作)时,才需要 Service Worker 文件中的上述代码。如果您需要的只是发送通知,那么您的消息对象应该只包含一个通知对象(只能接受一些固定键):

var message = {
  notification: {
    title: '850',
    body: '2:45'
  },
  token: registrationToken
};
Run Code Online (Sandbox Code Playgroud)