Handling Service Worker Messages:
let angularClient;
self.addEventListener('message', function(event) {
// store the client that sent the message in the angularClient variable
angularClient = event.ports[0];
});
Service Worker Notification Click Handler Sending Data to angularClient
self.addEventListener('notificationclick', function(event) {
event.notification.close();
var url = /localhost:8080|example.com|https:\/\/www.example.com/;
var newurl = "/" + event.notification.data.url;
if (event.notification.data.url) {
newurl = event.notification.data.url;
}
function endsWith(str, suffix) {
console.log(str);
console.log(suffix);
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
event.waitUntil(
clients.matchAll({
type: 'window'
})
.then(function(windowClients) {
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
if (url.test(client.url) && 'focus' in client) {
if (endsWith(client.url, newurl)) {
console.log("URL matched");
console.log("sending 1");
angularClient.postMessage(sendToAngularPayload);
return client.focus();
}
return client.navigate(newurl)
.then(client => client.focus());
}
}
if (clients.openWindow) {
console.log("sending 2");
angularClient.postMessage(sendToAngularPayload); //sendToAngularPayload is defined when notification is received in firebase's messaging.setBackgroundMessageHandler.
return clients.openWindow('https://www.example.com/#/' +
event.notification.data.url);
}
})
);
},true);
Controller Functions in AngularJs
Function to send a message to service worker to save this client
$scope.checkServiceWorker = function() {
if ('serviceWorker' in navigator) {
// make sure service worker is ready
navigator.serviceWorker.ready.then(function(reg) {
console.log("Sending message");
// PING to service worker, later we will use this ping to
// identify our client.
sendMessage().then(function(event) {
console.log(event);
}).catch(function(error) {
console.log("error", error);
location.reload();
});
}).catch(function() {
console.log('SW not ready');
$scope.checkServiceWorker();
});
}
}
sendMessage function with onMessage handler
function sendMessage() {
return new Promise(function(resolve, reject) {
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(event) {
console.log("on message handler", event);
if (event.data.error) {
reject(event.data.error);
} else {
console.log('inside resolve', event.data);
console.log("Ping received from SW");
console.log(event);
resolve(event.data);
}
};
console.log("Sending");
navigator.serviceWorker.controller.postMessage("ping",
[messageChannel.port2]);
console.log("sent");
});
}
The issue is that the onMessage Handler in the angularjs controller gets triggered 90% of the time, but occasionally it does not. When checking the developer console, I noticed that the execution halts in serviceworker.js after displaying "sending 1" in the notification click handler, and does not show any further logs inside the controller's onMessage handler.