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 内的链接 navigatefocus 可能是不好的做法,但现在,我只是想让它工作。然后我会尝试想出一个聪明的解决方案。

所以我的代码的问题是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.navigatenotificationclick 事件处理程序中工作。

因此,我只是发送了一个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的主要内容,如果未能解决你的问题,请参考以下文章

vue的生命周期

android 怎么打印service生命周期

请求生命周期:

浏览器 worker

手游生命周期的四类模型,你的游戏是哪种?

SAP MM物料生产生命周期-物料状态