0

I have a script that look at a phone call queue every second and display updates to the user. "for now my code writes messages to the console for testing purposes."

Since my code runs every 1 second, when a user opens multiple table, the same function is called 1 x "the total tabs" per second. If I have 5 tabs open, that is 5 requests per second, which could give the user false info or cause issues.

Is there a way for me to run the setInterval() function only on the active tab? My code will have to be executed on every page of the application to make sure the user is notify if there is an inbound call or something he or she needs to be aware of.

Here is the code that is executed every second.

<script>
$(function(){

    function isset(a, b){

        if(typeof a !== "undefined" && a){
            return a
        }

        return b;
    }

    setInterval(function() {

        $.getJSON("showMEssages.php", {method: "getMessages"}, function(data){

            if(typeof data.calls === 'undefined' || data.calls.length == 0 || !data.calls){
                console.log('No Messages');
                return;
            }

            $.each(data.calls, function(i, item){

                $.each(item, function(z, c){

                    var interactionId = isset(c.interactionId, 0);
                    var Eic_CallDirection = isset(c.Eic_CallDirection, '');
                    var Eic_State = isset(c.Eic_State, '');
                    var AccoRDI_mid = isset(c.AccoRDI_mid, '');
                    var Eic_RemoteAddress = isset(c.Eic_RemoteAddress, '');

                    if(Eic_State == '' || Eic_CallDirection == ''){
                        return;
                    }

                    //incoming call that is not answered
                    if( Eic_CallDirection == 'I' && Eic_State == 'A'){
                        console.log('Incomming Call From ' + Eic_RemoteAddress + ' MID: ' + AccoRDI_mid );
                        return;
                    }

                    //on hold
                    if( Eic_State == 'H'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on hold' );
                        return;
                    }

                    //voicemail
                    if( Eic_State == 'M'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on leaving a voicemail' );
                        return;
                    }

                    //connected call
                    if(Eic_State == 'C'){
                        console.log('Live Call With ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'O'){
                        console.log('Dialling ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'R'){
                        console.log('Outbound call is rining and waiting for answer ' );
                        return;
                    }

                    //Call Disconnected
                    if(Eic_State == 'I' || Eic_State == 'E' ){
                        console.log('Hungup with ' + Eic_RemoteAddress );
                        return;
                    }

                });
            });
        });

    }, 1000);
});
</script>

any alternative solution to this?

Jaylen
  • 39,043
  • 40
  • 128
  • 221
  • see [here](http://stackoverflow.com/questions/5927284/how-can-i-make-setinterval-also-work-when-a-tab-is-inactive-in-chrome) – Josh May 14 '15 at 22:18
  • This might be a better answer: http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active – Schlaus May 14 '15 at 22:20
  • Also, it's generally better to use `setTimeout()` instead of `setInterval()` in case something goes wrong. Just reinitialize the timeout in your callback if it should still keep running. – Schlaus May 14 '15 at 22:21
  • Polling from a server... Why not using [server-sent events](https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events) or [web sockets](http://stackoverflow.com/questions/9554896/sharing-websocket-across-browser-tabs)? – Rainer Rillke May 14 '15 at 22:28
  • @RainerRillke I like the server-sent event idea. To make sure I understand it correctly, when a server send a message to the client, will it execute the `ssedemo.php` page on the user's behalf? The `ssedemo.php` script will need to know the requester, before it can pull the correct username and password. – Jaylen May 15 '15 at 18:25
  • 1
    @Mike Not sure I understood the question in your comment correctly. In the above code sample you are polling from `showMEssages.php` without additional parameters like user name and password. The idea of server-sent events is similar to [long-polling](http://stackoverflow.com/a/12855533/2683737): The client (browser) sends a request to the server; the connection is kept alive and the server responds only and only when it has new data. Unless it is a cross-domain request the client will send cookies. Perhaps open a new question or search SO. – Rainer Rillke May 16 '15 at 09:25
  • @RainerRillke Thank you for your recomendation. Indeed I was able to implement it. but I am still running into the issue with multiple browser tabs. if I have 2 tabs or 2 broswers open and a new message is sent to the browser it will got to both tabs. How can I prevent this from happening? I want the message to be sent to only the active browser – Jaylen May 18 '15 at 20:28
  • @Mike did you see [the answer below](http://stackoverflow.com/a/30248844/2683737)? But I guess this is again not what you are after because a user could minimize a browser window and it would loose focus (but only have one open in total). And how realistically is that a user opens multiple browser windows? You can still switch all previously opened windows to an "expired" state. – Rainer Rillke May 19 '15 at 21:04

2 Answers2

0

You could implement some mechanism to synchronise the works between different tabs. The main idea is to let tabs communicate with each other

For example, once the user opens tabs, you broadcast a message to a channel saying it "I am looking for the active one". Then the active tab (listening on the same channel) will respond: "I am alive", and the new opened tab will not start the interval function. Otherwise it will start the interval and mark itself as active. In practice, you might need to do other things to eliminate deadlock (using watch dog technique for example)

There are other ways to do it but the general idea is to let tabs communicate with each other

Some libraries that might help you implement it

https://github.com/tejacques/crosstab

https://github.com/diy/intercom.js/

Tan Nguyen
  • 3,354
  • 3
  • 21
  • 18
  • Thank you for that. if I understand you correctly `intercom.js` is what I need to use. The method `.once` should do it. I should use it like this`.once(somethingRandom, myFunctionWithOutIntervalSet , [1])` am I correct? – Jaylen May 14 '15 at 23:50
  • Well there are many ways to use it. And Yes you can just go with `.once` for example when the user focuses on tab A you broadcast a message saying that all other tabs should stop the interval. And when the focus is in tab B, you repeat the process. That should do the trick – Tan Nguyen May 15 '15 at 00:47
0

I think it would be best to have a flag that you can check prior to executing your setTimeout callback, you can know if the tab has focus using window.onfocus and window.onblur:

var tabHasFocus = true;
window.onfocus = function() {
   tabHasFocus = true;
}
window.onblur = function() {
   tabHasFocus = false;
}

setInterval(function() {
   if(tabHasFocus) {
      ...
   }
}, 1000);
Rob M.
  • 35,491
  • 6
  • 51
  • 50