【发布时间】: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? 是否只能在处理激活事件时使用和导航到声明?
如果能提供任何帮助,我将不胜感激。
干杯
【问题讨论】:
标签: javascript push-notification firebase-cloud-messaging service-worker