ServiceWorker 在生命周期后期声称在 notificationclick 事件处理程序中使用 client.navigate
Posted
技术标签:
【中文标题】ServiceWorker 在生命周期后期声称在 notificationclick 事件处理程序中使用 client.navigate【英文标题】:ServiceWorker claiming late in the lifecycle to use client.navigate in notificationclick event handler 【发布时间】:2018-08-17 15:15:34 【问题描述】:我有一个 Firebase 服务人员,它在从 Firebase 云消息传递 (FCM) 推送消息时显示通知。
它还发布了一个帖子,以便我的 React 应用可以相应地更新。
/* eslint-env worker */
/* eslint no-restricted-globals: 1 */
/* global firebase */
/* global clients */
import config from './config'
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js')
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js')
const FIREBASE_MESSAGING_SENDER_ID = config
firebase.initializeApp( messagingSenderId: FIREBASE_MESSAGING_SENDER_ID )
const messaging = firebase.messaging()
messaging.setBackgroundMessageHandler(payload =>
const title = payload.data.title
const options =
body: payload.data.body,
icon: payload.data.icon,
data: payload.data,
clients.matchAll( includeUncontrolled: true ).then(clientz =>
clientz.forEach(client =>
sendMessageToClient(client, 'NEW_USER_NOTIFICATON')
)
)
return self.registration.showNotification(title, options)
)
const sendMessageToClient = (client, message) =>
const messageChannel = new MessageChannel()
client.postMessage(message, [messageChannel.port2])
这一切都很好,但我已经添加了它的上下文。
我想要做的是有一个点击功能,专注于正确的窗口/选项卡并导航到传递给它的链接。或者,如果选项卡未打开,请打开一个新窗口并转到链接。
这是我到目前为止的代码,添加到上述文件中。
self.addEventListener('notificationclick', event =>
const clickedNotification = event.notification
const link = clickedNotification.data.link
clickedNotification.close()
const promiseChain = self.clients.claim()
.then(() => self.clients
.matchAll(
type: 'window',
)
)
.then(windowClients =>
let matchingClient = null
windowClients.forEach(client =>
if (client.url.includes(matching_url))
matchingClient = client
)
if (matchingClient)
return matchingClient.navigate(link)
.then(() => matchingClient.focus())
return clients.openWindow(link)
)
event.waitUntil(promiseChain)
)
所以,我意识到 then
内的链接 navigate
和 focus
可能是不好的做法,但现在,我只是想让它工作。然后我会尝试想出一个聪明的解决方案。
所以我的代码的问题是clients.claim()
似乎不起作用。 matchAll
不返回任何内容到下一个then
,参数是一个空数组。
我可以简单地将includeUncontrolled: true
选项添加到matchAll
,但navigate
命令仅适用于受控客户端实例。
如果我尝试使用经常引用的Google example 进行声明和导航,它工作正常:
self.addEventListener('activate', event =>
event.waitUntil(self.clients.claim().then(() =>
// See https://developer.mozilla.org/en-US/docs/Web/API/Clients/matchAll
return self.clients.matchAll(type: 'window');
).then(clients =>
return clients.map(client =>
// Check to make sure WindowClient.navigate() is supported.
if ('navigate' in client)
return client.navigate('activated.html');
);
));
);
所以我被困住了。 serviceworker 会立即被激活,所以我假设它在那之后的任何时候都会声明一个客户端。
我是否爱上了一个随机的 ServiceWorker Gotcha? 是否只能在处理激活事件时使用和导航到声明?
如果能提供任何帮助,我将不胜感激。
干杯
【问题讨论】:
【参考方案1】:我无法让它工作。
但我认为值得记录我的解决方法。
我无法让client.navigate
在notificationclick
事件处理程序中工作。
因此,我只是发送了一个postMessage
,其中包含要在我的应用中提取的 URL 以触发那里的重定向,而没有任何客户端在任何地方声明。
self.addEventListener('notificationclick', event =>
const clickedNotification = event.notification
const link = clickedNotification.data.link
clickedNotification.close()
const promiseChain = self.clients.matchAll(
type: 'window',
includeUncontrolled: true,
)
.then(windowClients =>
let matchingClient = null
windowClients.forEach(client =>
if (client.url.includes(matching_url))
matchingClient = client
)
if (matchingClient)
sendMessageToClient(matchingClient, type: 'USER_NOTIFICATION_CLICKED', link )
return matchingClient.focus()
return clients.openWindow(link)
)
event.waitUntil(promiseChain)
)
const sendMessageToClient = (client, message) =>
const messageChannel = new MessageChannel()
client.postMessage(message, [messageChannel.port2])
【讨论】:
以上是关于ServiceWorker 在生命周期后期声称在 notificationclick 事件处理程序中使用 client.navigate的主要内容,如果未能解决你的问题,请参考以下文章