The client.postMessage() function in a service worker is not being recognized by the onmessage handler within an AngularJS controller

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.

Answer №1

service-worker.js

self.addEventListener("push", event => {
 const pushData = event.data.json();
 console.log("Push notification received:");
 console.log("data ", pushData);
 self.registration.showNotification(pushData.title, {
   body: "You have been notified!"
 })
 // Sending message from ServiceWorker to all clients
 self.clients.matchAll().then(clients => clients.map(client => client.postMessage(pushData)));
})

This listener is added on navigator.serviceWorker rather than a specific worker.

React Component:

constructor() {
    navigator.serviceWorker.addEventListener('message', e => console.log(e.data));
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Incorporating a PHP file containing both PHP and JavaScript variables into an AJAX document

I'm facing an issue with my application that involves a language file called "lang.php", along with "index.php" and "ajax.php" files. The "lang.php" file contains both PHP and JavaScript variables which I include in both "index.php" and "ajax.php" to ...

Copy the click function to a contenteditable <div> with spellcheck feature

When using a contenteditable <div> in Chrome, the native spell check feature will only work if the user manually clicks into the <div>. But what if you want to add a contenteditable <div> dynamically? Is there a way to trigger the spell c ...

Unable to forward with POST request in Node.js

I have a button on the front end that allows users to update their profile photo using the Cloudinary API. When the button is clicked, a Node.js POST request is sent with the user's data to query the database and update the profile photo URL. The func ...

Is JavaScript Gallery Acting Up? Possible Layer Glitch!

Seeking assistance with a website issue. I have an index.php file set up with a sideshow script in the head that appears on all pages. Additionally, within the index.php file, there is a portfolio.html page that displays a gallery script when loaded. The p ...

JavaScript function execution fails following an AJAX request

One of my functions is functioning properly with the alert: function RequestNext() { var xhr = getXMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 0)) { ...

Troubleshooting AngularJS expression issues when using ng-src within JSF framework

In this particular AngularJS module, the products array is defined with 2 product objects that will be assigned as a property of the controller. (function () { var app = angular.module('myApp', []); var products = [ { ...

Is it appropriate to use localStorage in the createSlice "reducers" parameter of React Redux Toolkit?

I'm working on implementing a basic favorites list feature. Currently, there is no backend functionality in place so this will be stored in the localStorage. It might potentially switch to an API call in the future. Would it be considered acceptable ...

Strategies for accessing array elements based on category

I am currently working with an array of diverse products var productList = [ { id: '1', category: 'todos', menuName: 'Empanada de Carne, Pollo o Mixta + Café 8oz.', menuPrice: '9.99&a ...

Switching the default browser for npm live-server

When I use the npm live-server package to preview my website as it changes, it keeps opening in Edge even though Chrome is set as my default browser on my system. I attempted to use the command suggested on the npm website: live-server --browser=chrome H ...

Injecting cascading style sheets across different domains using Javascript

Put simply: Is it possible for an external Javascript code to inject another script that is hosted on a completely different domain into the page's Document Object Model (DOM)? For example: Imagine the website foo.com which has an html script tag w ...

Switch up the query parameter in the current Vue router route

I am working on appending attribute parameters to a URL using the following code snippet: this.$router.push({ query: Object.assign({}, this.$route.query, { attributes: this.encodedAttributes() }) }); However, I have noticed that when I call this method fo ...

Creating a single-level menu with Bootstrap using nested angular ng-repeat

I am currently working on developing a single level menu using bootstrap and angularJS. The menu is successfully functioning with JavaScript and HTML when the <li> element is dynamically created. Now, I am attempting to integrate AngularJS into the ...

What is the proper way to specify a file destination in React?

After reading this article on downloading objects from GCP Cloud storage bucket, I'm curious about setting the file destination dynamically in React. Is there a way to achieve this? The article can be found at: https://cloud.google.com/storage/docs/do ...

Creating sequential hover animations with CSS in HTML

I have a total of four divs that I want to hover continuously, one after the other. Here is the code I am currently using: #rij1 .content-overlayz, #rij1 .content-details { animation-duration: 2s; animation-name: stepped-pulse; animation-iterati ...

creating a versatile axios function through object decomposition

Attempting to create a reusable axios function in my NodeJS project by parsing an object for multiple requests, and using the result of one request in subsequent ones. Previously hardcoded and chained axios requests, I need a more dynamic solution as the ...

Tips for incorporating the .click function with an overlay

Having some trouble using the .click function in conjunction with jQuery Tools overlay. HTML: <p id="click">Click here:</p> <div class="pop"> <div> <p>Insert text here</p> </div> </div> jQuery func ...

What is the best way to achieve a smooth rotation effect ranging from 1° to 359° using HTML/CSS in conjunction with JavaScript

Currently, I am retrieving rotation data from a sensor and transmitting it to a webpage containing a 2D-Model that rotates based on this data. To ensure a smoother motion, I have incorporated a CSS transition. However, an issue arises when the rotation da ...

Tips for adapting the position of a floating div according to its height and environment

Important Note: The code below utilizes the rubuxa plugin for handling JS sortables. Javascript: function querySelector(expr){return document.querySelector(expr)} var container = querySelector('.ITEST'); var sortable = Sortable.create(container, ...

Retrieving the output value from a callback function in Sqlite3

In my current project, I am using Sqlite3 with an Express backend along with a React frontend. My goal is to verify if a user with a specific email exists in the database. While working on the function provided below, which is still a work in progress, I e ...

Ways to extract information from JSON files

Currently, I am working on a script to extract viewer count and follower count data from Twitch. While I have successfully retrieved the viewer count information, I am encountering issues with extracting the follower count. The essential information can be ...