Push notification ServiceWorker WindowClient.navigate承诺被拒绝
我正在使用Firebase Cloud Messaging+服务工作者处理后台推送通知 单击通知(包含一些数据+URL)时,我想:Push notification ServiceWorker WindowClient.navigate承诺被拒绝,push-notification,firebase-cloud-messaging,service-worker,Push Notification,Firebase Cloud Messaging,Service Worker,我正在使用Firebase Cloud Messaging+服务工作者处理后台推送通知 单击通知(包含一些数据+URL)时,我想: 如果窗口已经位于所需的URL上,请将其聚焦 导航到URL,如果已打开活动选项卡,则将其聚焦 如果上述两个条件都不满足,请打开指向URL的新窗口 第1点和第3点适用于以下软件代码 出于某种原因,第2点不起作用。client.navigate()承诺被拒绝,原因是: Uncaught(in promise)类型错误:无法导航到URL:http://localhost
- 如果窗口已经位于所需的URL上,请将其聚焦
- 导航到URL,如果已打开活动选项卡,则将其聚焦
- 如果上述两个条件都不满足,请打开指向URL的新窗口
client.navigate()
承诺被拒绝,原因是:
Uncaught(in promise)类型错误:无法导航到URL:http://localhost:4200/tasks/-KMcCHZdQ2YKCgTA4ddd
我认为这可能是由于缺少https,但从我的阅读来看,似乎localhost在使用SW开发时被列入了白名单
firebase-messaging-sw.js:
// 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/3.5.3/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.3/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
'messagingSenderId': 'XXXX'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(payload => {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
let notificationData = JSON.parse(payload.data.notification);
const notificationOptions = {
body: notificationData.body,
data: {
clickUrl: notificationData.clickUrl
}
};
return self.registration.showNotification(notificationData.title,
notificationOptions);
});
self.addEventListener('notificationclick', event => {
console.log('[firebase-messaging-sw.js] Notification OnClick: ', event);
// 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.notification.close();
let validUrls = /localhost:4200/;
let newUrl = event.notification.data.clickUrl || '';
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
event.waitUntil(
clients.matchAll({
includeUncontrolled: true,
type: 'window'
})
.then(windowClients => {
for (let i = 0; i < windowClients.length; i++) {
let client = windowClients[i];
if (validUrls.test(client.url) && 'focus' in client) {
if (endsWith(client.url, newUrl)) {
console.log('URL already open, focusing.');
return client.focus();
} else {
console.log('Navigate to URL and focus', client.url, newUrl);
return client.navigate(newUrl).then(client => client.focus());
}
}
}
if (clients.openWindow) {
console.log('Opening new window', newUrl);
return clients.openWindow(newUrl);
}
})
);
});
//授予服务人员访问Firebase消息的权限。
//请注意,您只能在此处使用Firebase消息传递和其他Firebase库
//在服务人员中不可用。
进口文件('https://www.gstatic.com/firebasejs/3.5.3/firebase-app.js');
进口文件('https://www.gstatic.com/firebasejs/3.5.3/firebase-messaging.js');
//通过传入
//messagingSenderId。
firebase.initializeApp({
“messagingSenderId”:“XXXX”
});
const messaging=firebase.messaging();
messageing.setBackgroundMessageHandler(有效负载=>{
log(“[firebase messaging sw.js]接收到后台消息”,有效负载);
让notificationData=JSON.parse(payload.data.notification);
const notificationOptions={
body:notificationData.body,
数据:{
clickUrl:notificationData.clickUrl
}
};
返回self.registration.showNotification(notificationData.title,
通知选项);
});
self.addEventListener('notificationclick',event=>{
log(“[firebase messaging sw.js]通知OnClick:”,事件);
//当你点击通知时,Android不会关闭它
//见:http://crbug.com/463146
event.notification.close();
//这将查看电流是否已打开,并且
//如果是的话
event.notification.close();
设validUrls=/localhost:4200/;
让newUrl=event.notification.data.clickUrl | |“”;
函数endsWith(str,后缀){
返回str.indexOf(后缀,str.length-suffix.length)!=-1;
}
event.waitill(
客户。匹配球({
includeUncontrolled:正确,
键入:“窗口”
})
。然后(WindowClient=>{
for(设i=0;iclient.focus());
}
}
}
if(clients.openWindow){
console.log('打开新窗口',新建URL);
返回clients.openWindow(newUrl);
}
})
);
});
我的绝大多数软件代码取自:
我建议不要使用
客户端的includeUncontrolled:true
。matchAll()
您正在操作的WindowClient
可能没有当前的服务辅助程序作为其活动服务辅助程序。根据以下文件第4项:
如果上下文对象的关联服务工作者客户端处于活动状态
服务工作者不是上下文对象的相关全局对象的
服务人员,返回被拒绝的承诺,并带有TypeError
如果您可以在确定客户端当前由服务人员控制时重现该问题,则可能会发生其他情况,但这是我尝试的第一步。这对我来说很有效:
1-创建一个可观察的,并确保在解析之前不要调用消息传递API。
2-自己注册服务人员,首先检查其是否已注册
3-调用event.waitill(clients.claim());在您的服务人员中
private isMessagingInitialized$: Subject<void>;
constructor(private firebaseApp: firebase.app.App) {
navigator.serviceWorker.getRegistration('/').then(registration => {
if (registration) {
// optionally update your service worker to the latest firebase-messaging-sw.js
registration.update().then(() => {
firebase.messaging(this.firebaseApp).useServiceWorker(registration);
this.isMessagingInitialized$.next();
});
}
else {
navigator.serviceWorker.register('firebase-messaging-sw.js', { scope:'/'}).then(
registration => {
firebase.messaging(this.firebaseApp).useServiceWorker(registration);
this.isMessagingInitialized$.next();
}
);
}
});
this.isMessagingInitialized$.subscribe(
() => {
firebase.messaging(this.firebaseApp).usePublicVapidKey('Your public api key');
firebase.messaging(this.firebaseApp).onTokenRefresh(() => {
this.getToken().subscribe((token: string) => {
})
});
firebase.messaging(this.firebaseApp).onMessage((payload: any) => {
});
}
);
}
}
为了进一步了解Jeff的评论,firebase-messaging-sw.js肯定不会控制页面,这是出于设计。如果需要此行为,可以将自定义服务工作人员注册传递到
messaging.useServiceWorker()
。此服务人员注册可以控制源站上的所有页面,并允许使用navigate()调用。@Jeff-我发现客户端。matchAll()
没有返回任何WindowClient,除非我包含不受控制的窗口,这在@Gaunt刚刚提到的情况下是有意义的。谢谢你们两位的建议,我会让你们知道这是怎么回事,一旦我的答案生效,我可能会把它标记为可接受的答案。@Gaunface你们能详细说明一下吗?我已将自己的serviceworker传递给messaging.useServiceWorker,但收到了相同的错误。请打开一个新问题,列出您收到的示例文件位置、文件内容和错误消息。@rabhw您是否找到了此问题的解决方案,我们面临着类似的情况,它在firefox中工作,但在Chrome浏览器中出现了类似的错误。非常感谢您的帮助,谢谢
self.addEventListener('notificationclick', function (event) {
event.notification.close();
switch (event.action) {
case 'close': {
break;
}
default: {
event.waitUntil(clients.claim());// this
event.waitUntil(clients.matchAll({
includeUncontrolled: true,
type: "window"
}).then(function (clientList) {
...
clientList[i].navigate('you url');
...
}
}
}