我有一个小型网络应用程序,它接收 FCM 消息,有一个服务 worker ,处理后台消息,一切都很好。 Service Worker 将接收消息并将它们发布回主页,以便它们可以显示在页面上。这是背景消息。
我的问题是前台消息由一些默认的 onMessage() 处理,它将它们作为封装在大消息中的消息传递给主页。所以,假设,如果我在 .js 或主页本身中定义了自己的 onMessage() 函数,将调用此消息,然后调用默认消息,这会导致消息被处理两次。
以下是我收到的消息:
Service Worker 中的代码是:
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 = {
apiKey: "AIzaSyBoi6gB1BHKxFBt58JJ4phWiZr9BKJaphI",
authDomain: "webmessaging-7bef1.firebaseapp.com",
databaseURL: "https://webmessaging-7bef1.firebaseio.com",
projectId: "webmessaging-7bef1",
storageBucket: "webmessaging-7bef1.appspot.com",
messagingSenderId: "649072625962"
};
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
'messagingSenderId': '649072625962'
});
const messaging = firebase.messaging();
self.addEventListener('notificationclick', function (event) {
console.log('On notification click: ', event.notification.tag);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
includeUncontrolled: true,
type: "all"
})
.then(function (clientList) {
console.log('Clients Count: ', clientList.length);
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
var clientUrl = client.url;
console.log('Client URL:', client.url);
if ((clientUrl.indexOf("localhost") != -1) && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWindow('https://deanhume.github.io/typography');
}
})
);
});
messaging.setBackgroundMessageHandler(function (payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = payload.data.title;
const notificationOptions = {
body: payload.data.body,
icon: '/fcm-logo.png'
};
clients.matchAll({
includeUncontrolled: true,
type: "all"
})
.then(function (clientList) {
console.log('Clients Count: ', clientList.length);
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
var clientUrl = client.url;
console.log('Client URL:', client.url);
if ((clientUrl.indexOf("localhost") != -1) && 'focus' in client) {
// client.postMessage(payload.data);
}
}
})
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
如果我删除我的 onMessage() 处理程序,我仍然会收到默认的 onMessage() 处理程序发布的消息。
请指教。
谢谢...
[更新] 经过一些彻底的检查后,我得出了一些结论,问题似乎在于我有以下两个函数,它们似乎通过接收发送到页面的消息来做完全相同的事情。
这个页面应该在页面位于前台并获得焦点时接收消息。
messaging.onMessage(function (payload) {
console.log('Message received: ', payload);
alert(payload.data.title);
// Get the data passed by the message and display on the page...
document.getElementById('Select1').innerHTML += "<option>" + payload.data.title + "</option>";
});
而这个是指在页面处于后台且没有焦点的情况下接收消息时接收服务人员传递的数据。
// Listen to messages from service workers.
navigator.serviceWorker.addEventListener('message', function (event) {
console.log("Got reply from service worker: ", event);
// Get the data passed by the message and display on the page...
document.getElementById('Select1').innerHTML += "<option>" + event.data.title + "</option>";
});
所以,基本上,我在同一个地方同时通过两个处理程序收听消息,这导致消息被同时处理两次...... 任何建议我如何正确组织此代码?
最佳答案
一些注意事项:
1- 您不应该在 service worker 中包含配置详细信息(因为它位于客户端)并将其限制为所需的:
firebase.initializeApp({
'messagingSenderId': '649072625962'
});
2- messaging.setBackgroundMessageHandler 仅在后台情况下触发。
3- messaging.onMessage() 您没有在服务工作人员中定义,而是在 .js 中定义,正如您提到的那样,用于处理前台场景的情况,并且将仅在那case(在你定义它之前没有它的默认定义)
关于javascript - FCM 默认 onMessage 覆盖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48556825/