web-dev-qa-db-ja.com

serviceworkersフォーカスタブ:notificationclickでクライアントが空になります

一般的なサービスワーカーのシナリオがあります。通知のクリックをキャッチして、通知の送信元のタブにフォーカスします。ただし、clients変数は常に空であり、その長さは0です。

console.log("sw startup");
self.addEventListener('install', function (event) {
    console.log("SW installed");
});

self.addEventListener('activate', function (event) {
    console.log("SW activated");
});
self.addEventListener("notificationclick", function (e) {
    // Android doesn't automatically close notifications on click 
    console.log(e);
    e.notification.close();
  
    // Focus tab if open
    e.waitUntil(clients.matchAll({
        type: 'window'
    }).then(function (clientList) {
        console.log("clients:" + clientList.length);
        for (var i = 0; i < clientList.length; ++i) {
            var client = clientList[i];
            if (client.url === '/' && 'focus' in client) {
                return client.focus();
            }
        }

        if (clients.openWindow) {
            return clients.openWindow('/');
        }
    }));
    
});

そして登録はこれです:

 this.doNotify = function (notification) {      
        if ('serviceWorker' in navigator) {
            navigator.serviceWorker.register('sw.js').then(function (reg) {
               
                requestCreateNotification(notification, reg);
            }, function (err) {
                console.log('sw reg error:' + err);
            });
        }
   ...
   }

chrome:// serviceworker-internals /の出力は、登録とインストールが正常であることを示しています。ただし、通知がプッシュされると、clientListは空になります。フィルタタイプ「ウィンドウ」を削除しようとしましたが、結果は同じです。クライアントが空であるため、新しいウィンドウが常に開かれます。私は何が間違っているのですか?

18
moarra

あなた自身のコメントの疑惑は正しいです。ページはサービスワーカーによって制御されますサービスワーカーが登録されているオリジンへのナビゲーション上。したがって、実際にServiceWorkerを初期化する元のページの読み込み自体は制御されません。そのため、新しいタブにアクセスするか、更新を行うと、ワーカーはタブを見つけるだけです。

ただし、(Jeff Posnickがコメントで指摘しているように)次のように制御されていないページを取得できます:ServiceWorkerClients.matchAll({includeUncontrolled: true, type: 'window'})

35
Brendan Ritchie

サービスワーカーにすぐにページを要求させてみてください。例えば。:

self.addEventListener('install', event => event.waitUntil(self.skipWaiting()));

self.addEventListener('activate', event => event.waitUntil(self.clients.claim()));

より複雑な例については、 https://serviceworke.rs/immediate-claim.html を参照してください。

4
Marco