服务工作者“notificationclick”未触发
Posted
技术标签:
【中文标题】服务工作者“notificationclick”未触发【英文标题】:Service Worker "notificationclick" not firing 【发布时间】:2020-11-11 21:06:41 【问题描述】:通知显示正常,但是当我单击它或执行任何操作时,什么都没有发生。我没有看到任何日志记录,也没有错误消息,但通知确实关闭了(尽管即使我注释掉 event.notification.close()
它也会关闭)。
我尝试使用 Chrome 调试器,并且可以在显示通知的代码中设置断点,但 notificationclick
处理程序中的所有断点都无法暂停执行。
我花了几天的时间试图让它工作,但我束手无策。
const auth = firebase.auth();
const functions = firebase.functions();
const done = functions.httpsCallable("done");
const snooze = functions.httpsCallable("snooze");
self.addEventListener("notificationclick", event =>
console.log("notificationclick", event);
const uid = auth.currentUser.uid;
const id, url = event.notification.data;
event.notification.close();
event.waitUntil(() =>
switch (event.action)
case "done":
console.log("Done");
return done( uid, id );
case "snooze1":
console.log("Snooze 1 Hour");
return snooze( uid, id, hours: 1 );
case "snooze24":
console.log("Snooze 1 Day");
return snooze( uid, id, hours: 24 );
default:
console.log("Open App");
return clients
.matchAll(
includeUncontrolled: true,
type: "window"
)
.then(clientList =>
for (let i = 0; i < clientList.length; i++)
let client = clientList[i];
if (url[0] === "#")
if (client.url.endsWith(url) && "focus" in client)
return client.focus();
else
if (
client.url.replace(/#.*$/, "") === url &&
"focus" in client
)
return client.focus();
if (clients.openWindow)
return clients.openWindow(location.origin + url);
);
);
);
firebase
.messaging()
.setBackgroundMessageHandler(( data: title, options ) =>
options = JSON.parse(options);
options.actions = [
action: "done", title: "Done" ,
action: "snooze1", title: "Snooze 1 Hour" ,
action: "snooze24", title: "Snooze 1 Day"
];
return self.registration.showNotification(title, options);
);
【问题讨论】:
【参考方案1】:你好,你可以试试下面的代码,看看它是否被调用-
self.addEventListener('notificationclick', function (event)
event.notification.close();
var redirectUrl = null;
var tag = event.notification.tag;
if (event.action)
redirectUrl = event.action
if (redirectUrl)
event.waitUntil(async function ()
var allClients = await clients.matchAll(
includeUncontrolled: !0
);
var chatClient;
for (const client of allClients)
if (redirectUrl != '/' && client.url.indexOf(redirectUrl) >= 0)
client.focus();
chatClient = client;
break
if (chatClient == null || chatClient == 'undefined')
chatClient = clients.openWindow(redirectUrl);
return chatClient
().then(result =>
if (tag)
//PostAction(tag, "click")
))
);
编辑- 附加两个js文件。它在我的最后工作。
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');
var config =
apiKey: "your api key",
authDomain: "you firebase domain",
databaseURL: "your firbase db url",
projectId: "your project id",
storageBucket: "",
messagingSenderId: "sender id"
;
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload)
console.log('[firebase-messaging-sw.js] Received background message ', payload.data);
var notificationTitle = payload.data.Title;
var notificationOptions =
body: payload.data.Body,
icon: payload.data.Icon,
image: payload.data.Image,
action: payload.data.ClickAction
;
console.log("strated sending msg" + notificationOptions);
return self.registration.showNotification(notificationTitle,notificationOptions);
);
self.addEventListener('notificationclick', function (event)
console.log('On notification click: ', event.notification);
event.notification.close();
var redirectUrl = null;
if (event.notification.data)
if (event.notification.data.FCM_MSG)
redirectUrl = event.notification.data.FCM_MSG.data ? event.notification.data.FCM_MSG.data.click_action : null
else
redirectUrl = event.notification.data ? event.notification.data.click_action : null
console.log("redirect url is : " + redirectUrl);
if (redirectUrl)
event.waitUntil(async function ()
var allClients = await clients.matchAll(
includeUncontrolled: true
);
var chatClient;
for (var i = 0; i < allClients.length; i++)
var client = allClients[i];
if (client['url'].indexOf(redirectUrl) >= 0)
client.focus();
chatClient = client;
break;
if (chatClient == null || chatClient == 'undefined')
chatClient = clients.openWindow(redirectUrl);
return chatClient;
());
);
self.addEventListener("notificationclose", function (event)
event.notification.close();
console.log('user has clicked notification close');
);
application.js
文件:
/// <reference path="scripts/jquery-3.3.1.js" />
try
var config =
apiKey: "your api key",
authDomain: "you firebase domain",
databaseURL: "your firbase db url",
projectId: "your project id",
storageBucket: "",
messagingSenderId: "sender id"
;
firebase.initializeApp(config);
if ('serviceWorker' in navigator && 'PushManager' in window)
console.log('Service Worker and Push is supported');
navigator.serviceWorker
.register('/firebase-messaging-sw.js')
.then((swReg) =>
firebase.messaging().useServiceWorker(swReg);
askForPermissioToReceiveNotifications();
)
.catch(function (error)
console.error('Service Worker Error', error);
window.alert("Service Worker Error" + error);
)
else
console.warn('Push messaging is not supported');
window.alert("Push messaging is not supported " + (navigator.serviceWorker));
const askForPermissioToReceiveNotifications = async () =>
try
const messaging = firebase.messaging();
console.log(messaging);
await messaging.requestPermission();
const token = await messaging.getToken();
if (token !== null || token !== 'undefined')
await sendDeviceTokenToServerSide(token);
console.log('Got token : ' + token);
messaging.onMessage(function (payload)
console.log('onMessage: ', payload);
setTimeout(() =>
navigator.serviceWorker.ready.then(function (registration)
var notificationTitle = payload.notification.title;
var notificationOptions =
body: payload.notification.body,
data: payload.data,
icon: payload.notification.icon,
image: payload.data.Image,
requireInteraction: payload.notification.requireInteraction,
tag: payload.notification.tag,
click_action: payload.data.click_action,
requireInteraction: true
;
registration.showNotification(notificationTitle, notificationOptions);
,50)
);
);
catch (e) console.log('error in getting token: ' + e); window.alert("error in getting token: " + e);
function sendDeviceTokenToServerSide(token)
$.ajax(
type: 'POST',
url: '/Home/StoreToken',
timeout: 5000000,
data: token: token ,
success: function (success)
console.log("device token is sent to server");
,
error: function (error)
console.log("device error sending token to server : " + error);
window.alert("device error sending token to server : " + error);
);
catch (e)
window.alert("error: " + e);
function GetFcmUserToken(messaging)
messaging.onTokenRefresh(function ()
messaging.getToken()
.then(function (refreshedToken)
console.log('Token refreshed.');
return refreshedToken;
)
.catch(function (err)
console.log('Unable to retrieve refreshed token ', err);
showToken('Unable to retrieve refreshed token ', err);
);
);
【讨论】:
你的代码和我的代码一样。 你的代码在 serviceworker.js/firebase-messaging-sw.js 下对吗? 是的,文件中的其余代码正在运行。我就是无法触发点击处理程序。 当网站同时处于前台和后台或仅在后台时会发生这种情况? 该通知仅在网站处于后台时出现。我认为这种行为是由 Firebase 消息处理的。【参考方案2】:self.addEventListener('notificationclick', function (event)
const clickedNotification = event.notification;
// Do something as the result of the notification click
const promiseChain = clients.openWindow(clickedNotification.data.Url);
event.waitUntil(promiseChain);
);
Service Worker js 中的这段代码在 Chrome 桌面和 android 上运行良好。
【讨论】:
以上是关于服务工作者“notificationclick”未触发的主要内容,如果未能解决你的问题,请参考以下文章
ServiceWorker 在生命周期后期声称在 notificationclick 事件处理程序中使用 client.navigate
服务工作者 - 等待client.openWindow在postMessage之前完成