Search code examples
laravelweb-workerpusherpusher-jsshared-worker

Pusher - Shared web worker variable scope


I'm using a shared worker for a pusher in Laravel, Here XYZABC is my pusher key as string, but is there a way I can use ENV variable or variables defined in my blade file so I don't have to hard-code key there, and also need to switch channels based on country. so is there a way to access java-script variables defined in blade inside a shared worker script? this is my code

This is the sample code from the pusher community I worked on

https://github.com/pusher-community/pusher-with-shared-workers

// Pusher notification works as shared worker thread for providing
// notification across different tab for the same user, thereby reducing 
// channel count per user

importScripts("../../common/pusher.worker.min.js");


// An array of the clients/tabs using this worker
var clients = [];


// Connect to Pusher
var pusher = new Pusher("XYZABC", {
    encrypted: true,
    cluster: 'ap2',
    useTLS : true
});


// Log pusher details to console
Pusher.logToConsole = true
// Subscribe to the channel we specified in our Laravel Event
var channel = pusher.subscribe('task-created');


// Bind a function to a Event (the full Laravel class)
channel.bind('App\\Events\\TaskCreated', function(data) {
    // Relay the message on to each client
    clients.forEach(function(client){
        client.postMessage(data);
    });
});


self.addEventListener("connect", function(evt){
    // Add the port to the list of connected clients
    var port = evt.ports[0];
    clients.push(port);

    // Start the worker.
    port.start();
});

Solution

  • After few research, found out workers can only communicate using postMessage or onmessage. so passed my key and country details on postMessage after worker start.

    PS: Not sure if this is the correct work around or doing anything wrong here, do comment if there is better solution or mistake.

    here's my Main thread

    if (typeof(window.SharedWorker) === 'undefined') {
        throw("Your browser does not support SharedWorkers")
    } else {
        // Start our new worker
        var worker = new SharedWorker(basePath+"/assets/frontend/js/pusher-worker.min.js");
        console.log('Worker:', worker);
    
        // Whenever we get a message, set the #message element to the data brought in
        worker.port.onmessage = function(evt){
            // Log's the data recieved from shared worked
            console.log(evt.data);
        };
    
        // If we get an error, log it out and close the worker.
        worker.onerror = function(err){
            console.log(err.message);
            worker.port.close();
        }
    
        // Start the worker.
        worker.port.start();
    
        // Post pusher key and country code to worker thread
        worker.port.postMessage({key : pusherkey, country : pusherHomeCountryCode});
    }
    

    here's my modified Worker thread

    // Pusher notification works as shared worker thread for providing
    // notification across different tab for same user, there by reducing 
    // channel count per user
    
    importScripts("../../common/pusher.worker.min.js");
    
    
    // An array of the clients/tabs using this worker
    var clients = [];
    
    // Flag to initialize pusher only once
    var initialize = false;
    
    // These two variable value will be recieved on post message from main thread
    var pusherKey = null;
    var countryCode = null;
    
    // Function to initialize pusher and subscribe to a channel
    function initalizePusherFn(pusherKey, countryCode) {
        // Connect to Pusher
        var pusher = new Pusher(pusherKey, {
            encrypted: true,
            cluster: 'ap2',
            useTLS : true
        });
    
    
        // Log pusher details to console
        Pusher.logToConsole = true
    
        // Subscribe to the channel we specified in our Laravel Event
        var channelName = 'task-created';
        if(typeof countryCode != 'undefined' && countryCode != '' && countryCode != 'PH'){
            channelName = channelName+"-"+countryCode;
        }
        var channel = pusher.subscribe(channelName);
    
        // Bind a function to a Event (the full Laravel class)
        channel.bind('App\\Events\\TaskCreated', function(data) {
            // Relay the message on to each client
            clients.forEach(function(client){
                client.postMessage(data);
            });
        });
    }
    
    self.addEventListener("connect", function(evt){
        // Add the port to the list of connected clients
        var port = evt.ports[0];
        clients.push(port);
    
        // On first load a post message will be called to pass pusherkey and country
        port.addEventListener('message', function(eventM){
            var data = eventM.data;
            pusherKey = data.key;
            countryCode = data.country;
    
            console.log(' initialize value:', initialize, '\n');
            console.log(' key:', pusherKey, '\n');
            console.log(' country code: ', countryCode, '\n');
            
            // Check if pusher is already initialized,
            // if not initialize and subscribe to a channel based on country
            // this should onle be working once for multiple tabs, else channel and 
            // message count will increase for pusher
            if(!initialize)
                initalizePusherFn(pusherKey, countryCode);
    
            // set initialize as true after being initialized
            initialize = true;
        }, false);
    
        // Start the worker.
        port.start();
    });