即使在发送消息后,也不会在 React 应用程序中触发 Firebase 云消息传递 onMessage
Posted
技术标签:
【中文标题】即使在发送消息后,也不会在 React 应用程序中触发 Firebase 云消息传递 onMessage【英文标题】:Firebase cloud messaging onMessage not triggered in React app even after message is sent 【发布时间】:2019-08-28 18:03:30 【问题描述】:我正在我的 React 应用程序中测试 Firebase 云消息传递功能,该应用程序由 create-react-app 引导。请注意,我已经正确初始化了 firebase(包括服务器端的管理 SDK),并且我的客户端部署在 https 上。到目前为止,我所做的是:
-
在 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);
);
-
在公共目录中创建 service worker 文件 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();
-
我从另一个 *** 帖子中读到,在 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);
);
-
为了轻松测试消息传递,我在 Main.js 中添加了一个按钮,该按钮将在单击时将令牌发送到我的服务器(然后服务器将继续发送消息)
const handlePushButtonClick = () =>
messaging.getToken().then(token =>
axios.post(<Server link hidden>,
token
);
);
;
-
然后我像这样在我的快速服务器中设置必要的路由
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);
);
);
这是问题所在,我已验证我的服务器已成功接收令牌并且实际上已成功发送消息,但在我的客户端,我根本没有收到 onMessage 有效负载对象。
从我的代码中回想一下,我希望在客户端开发控制台上收到的是带有 onMessage 和有效负载的 console.log。
messaging.onMessage(payload =>
console.log("onMessage: ", payload);
);
【问题讨论】:
【参考方案1】:解决此问题的简单方法是将您的 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');
注意:一旦您更新了您的 firebase 库版本,那么 messagingSenderId 将无法在您的 firebase-messaging-sw.js 文件中使用。您必须提供所有其他参数,例如。 apiKey、projectId、appId 以及 messagingSenderId。
例如。
在你的 firebase-messaging-sw.js
中替换它firebase.initializeApp(
messagingSenderId: "Sender ID"
);
有了这个
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",
);
如果还是不行。清理浏览器缓存并重新注册 Service Worker。
【讨论】:
但是来自服务工作者的后台通知确实可以单独使用messagingSenderId。 @andreszs 如果您将 Firebase sdk 更新为最新版本(firebasejs/7.8.0/firebase-app.js' & firebasejs/7.8.0/firebase-messaging.js)。它会告诉你错误。 SW 中缺少某种项目 ID。要解决这个问题,您需要添加其余的详细信息。并且经过测试。 要触发 onMessage 事件,您必须更新您的 Firebase SDK。 9.6.1 上同样的问题【参考方案2】:我发现了我的错误。我最初遵循本指南:https://firebase.google.com/docs/cloud-messaging/js/topic-messaging。当我按照教程进行操作时,我之前的错误对我来说不是很清楚,但这可能是因为我对通知和推送 Web API 非常不熟悉。
教程的消息对象里面有一个数据对象:
var message =
data:
score: '850',
time: '2:45'
,
token: registrationToken
;
事实证明,如果我想在消息中发送数据负载,我需要在我的 firebase-messaging-sw.js 中包含这组代码(我链接的教程中没有显示这一点):
messaging.setBackgroundMessageHandler(payload =>
const title = payload.data.title;
const options =
body: payload.data.score
;
return self.registration.showNotification(title, options);
);
请注意,仅当您要发送数据有效负载(此后您可以在 service worker 文件中灵活操作)时,才需要 service worker 文件中的上述代码。如果你只需要发送一个通知,你的消息对象应该简单地包含一个通知对象(它只能接受一些固定的键):
var message =
notification:
title: '850',
body: '2:45'
,
token: registrationToken
;
【讨论】:
前台和后台应该有相同的有效载荷。您为通知建议了两种不同的解决方案。根据您的逻辑,如果要发送前台消息需要使用通知有效负载。而对于后台消息需要使用数据有效载荷。但这种解决方案并不理想。使用上述解决方案,您将仅通过数据有效负载来实现两者。以上是关于即使在发送消息后,也不会在 React 应用程序中触发 Firebase 云消息传递 onMessage的主要内容,如果未能解决你的问题,请参考以下文章
即使 DB 已正确更新,React UI 也不会在单击时重新呈现。第二次点击后,UI 重新渲染
即使在调用 setState 之后,React.js 子状态也不会重新渲染?
即使使用代理,Nodejs 也不会为 React CRA 应用程序设置 cookie
在 SockJsClient (React) 中握手后无法发送消息