3

我正在使用Firebase云消息传递+服务工作人员来处理后台推送通知。ServiceWorker WindowClient.navigate承诺拒绝

当点击(其中包含一些数据+一个URL)的通知,我想要么:

  • 焦点,如果它已经在所需的URL
  • 导航到URL并将其聚焦窗口如果已经有一个有源标签开放
  • 打开一个新的窗口的URL,如果既不的上述条件满足

点1,并用下面的代码SW 3的工作。

由于某些原因,点#2不起作用。该client.navigate()承诺被拒绝使用:

Uncaught (in promise) TypeError: Cannot navigate to URL: http://localhost:4200/tasks/-KMcCHZdQ2YKCgTA4ddd

我想这可能是由于缺乏HTTPS的,但是从我读它,就好像在与SW开发本地主机列入白名单出现。

火力点的消息,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); 
     } 
    }) 
); 

}); 

绝大多数的我SW代码摘自: https://gist.github.com/vibgy/0c5f51a8c5756a5c408da214da5aa7b0

回答

3

我建议你从你的clients.matchAll()离开了includeUncontrolled: true

您正在处理的WindowClient可能没有将当前服务工作人员作为其活动服务工作人员。由于每个项目4 the specification for WindowClient.navigate()

如果上下文对象的相关服务人员客户的主动服务 工人不是上下文对象的有关全局对象的 服务人员,返回一个TypeError拒绝承诺。

如果能重现问题,当你确定客户端目前由服务人员控制,那么有可能是别的事情,但是这就是我想尝试的第一步。

+2

为了进一步杰夫的评论,firebase-messaging-sw.js将*绝对*不是控制页面,这是设计。如果你想要这种行为,你可以将一个自定义的服务工作者注册传递给'messaging.useServiceWorker(<你的注册在这里>)'。这个服务工作者注册可以控制你的源的所有页面,并允许使用navigate()调用。 –

+1

@Jeff - 我发现'clients.matchAll()'没有返回任何WindowClients,除非我包含了不受控制的窗口,这在给出@Gaunt刚刚提到的内容时有意义。 谢谢你们的建议,我会让你知道这是怎么回事,一旦我得到它的工作可能将其标记为公认的答案。 – rabhw

+1

@GauntFace你能详细解释一下吗?我已将自己的服务人员传递给messaging.useServiceWorker,但得到相同的错误。 – user2145184