Несовместимые данные через push-обновление - одновременно работают несколько сервисных работников? - PullRequest
0 голосов
/ 21 декабря 2018

Кажется, что мой PWA создает несколько сервисных работников, что приводит к непоследовательному поведению при получении push-уведомлений через FCM.(Я отправляю Push всем fcmTokens пользователя, который работает - я успешно получил уведомления на нескольких устройствах, открытых одновременно).Например, я открываю одну вкладку с помощью PWA и отправляю на нее уведомление.Chrome отобразит сообщение Push-уведомления, но открытая вкладка не будет обновлена.Если я нажимаю на уведомление (чтобы открыть тот же URL, на котором размещен PWA), он открывает новую вкладку (теперь есть 2 вкладки с тем же URL и тем же PWA), и только та вкладка обновляется / получает push-уведомления.,Эта вкладка теперь работает полностью, как и ожидалось, и именно так я хочу, чтобы PWA вел себя при первом открытии (без щелчка по уведомлению).Может быть, это также проблема кэширования, и у меня запущены две версии приложения, и только одна из них получает обновления?

Я заметил такое же поведение на смартфоне - новая развернутая версия PWA не получает обновления, пока янажмите на уведомление, которое иногда происходит, а иногда нет.Даже если это так, приложение иногда обновляет свои данные, а иногда нет.

Помогите мне решить проблему и получите согласованное поведение при получении push-уведомлений в моем PWA.

Я уже пытался удалить данные кэша / приложения перед запуском PWA, но проблема все еще остается.

Мой сервисный работник:

'use strict';

importScripts('./build/sw-toolbox.js');

const version = 0.83;

self.toolbox.options.cache = {
name: 'ionic-cache'
};

// pre-cache our key assets
self.toolbox.precache(
[
    './build/main.js',
    './build/vendor.js',
    './build/main.css',
    './build/polyfills.js',
    'index.html',
    'manifest.json'
]
);

// dynamically cache any other local assets
self.toolbox.router.any('/*', self.toolbox.fastest);

// for any other requests go to the network, cache,
// and then only use that cached resource if your user goes offline
self.toolbox.router.default = self.toolbox.networkFirst;

importScripts('https://www.gstatic.com/firebasejs/5.5.9/firebase-                            app.js');
importScripts('https://www.gstatic.com/firebasejs/5.5.9/firebase-messaging.js');

firebase.initializeApp({
'messagingSenderId': 'XXXX'
});

self.addEventListener('install', function (event) {
// The promise that skipWaiting() returns can be safely ignored.
self.skipWaiting();

// Perform any other actions required for your
// service worker to install, potentially inside
// of event.waitUntil();
});

self.addEventListener("notificationclick", function (event) {
/**event.notification.close();
 event.waitUntil(clients.openWindow("/")); **/
const rootUrl = new URL('/', location).href;
event.notification.close();
// Enumerate windows, and call window.focus(), or open a new     one.
event.waitUntil(
    clients.matchAll().then(matchedClients => {
        for (let client of matchedClients) {
            if (client.url === rootUrl) {
                return client.focus();
            }
        }
        return clients.openWindow("/");
    })
);
});

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function (payload) {
let swPushedessageData = payload.data;
swPushedessageData.job = JSON.parse(payload.data.job);
let notificationTitle;
switch (swPushedessageData.action) {
    case 'DELETE':
        notificationTitle = 'Auftrag gelöscht';
        break;
    case 'CREATE':
        notificationTitle = 'Neuer Auftrag zugewiesen';
        break;
    case 'UPDATE':
        notificationTitle = 'Auftragsänderung';
        break;
}

const notificationOptions = {
    icon: '/assets/icon/icon-128x128.png',
    actions: [{action: 'open', title: 'Öffnen'}],
};
send_message_to_all_clients(swPushedessageData);

return self.registration.showNotification(notificationTitle,
    notificationOptions);
});

function send_message_to_all_clients(msg) {
clients.matchAll().then(clients => {
    clients.forEach(client => {
        send_message_to_client(client, msg).then(m =>         console.log("SW Received Message: " + m));
    })
})
}

function send_message_to_client(client, msg) {
return new Promise(function (resolve, reject) {
    const msg_chan = new MessageChannel();

    msg_chan.port1.onmessage = function (event) {
        if (event.data.error) {
            reject(event.data.error);
        } else {
            resolve(event.data);
        }
    };

    client.postMessage(msg, [msg_chan.port2]);
});
}

Установка Сервисного работника в приложении:

navigator.serviceWorker.register('service-worker.js')
.then((registration) => {
        const messaging = this.app.messaging();
        this.swIsActive = true;
        messaging.useServiceWorker(registration);
        this.checkPushMessagingPermissionAfterLogin();
        this.swRegistration = registration;
    })
...