Search code examples
javascriptjqueryglobal-variablesprototypesynchronize

How can I synchronize accessing a global var across two external JS files


test.html

<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
        <script src = "./test1.js"></script>
        <script src = "./test2.js"></script>
    </head>
</html>

test1.js

var a;
$(document).ready(function(){
    setTimeout(function(){
        a=10;   
    },1000);
});

test2.js

$(document).ready(function(){
    //Busy waiting... doesn't Work.
    /*while(typeof(a) === "undefined"){
        console.log(a);
    };*/
    console.log(a);
});

test2 prints 'a' is 'undefined'... How can I synchronize 'a' over two javascript files?


Solution

  • The reason busy-waiting didn't work is that JavaScript on browsers has only one main thread, so the busy-wait was preventing the code from test1.js from ever running. Busy-waiting is almost never a good idea in general, and essentially never a good idea in browser-based JavaScript. :-)

    Ideally, the two files would provide an intentional way to synchronize between them.

    But if there is no event that test2.js can use, and if it's definitely correct to wait until a has a value other than undefined, you can use a setTimeout loop:

    test2.js:

    $(document).ready(function(){
        function checkForA() {
            if (typeof a === "undefined") {
                // Keep waiting
                setTimeout(checkForA, 10); // 50 = 50 milliseconds
            } else {
                // Got it
                console.log(a);
            }
        }
    
        checkForA();
    });
    

    If it's possible to avoid this timeout loop by using some kind of notification from test1.js, that would be better; but in the worst case, polling every 50ms or so isn't a big deal. It may be a good idea to have it give up at some point:

    $(document).ready(function(){
        var started = Date.now();
    
        function checkForA() {
            if (typeof a === "undefined") {
                // Still don't have it, keep waiting?
                if (Date.now() - start > 10000) { // More than 10 seconds
                    // Give up
                    console.log("Gave up waiting for a");
                } else {
                    setTimeout(checkForA, 10); // 50 = 50 milliseconds
                }
            } else {
                // Got it
                console.log(a);
            }
        }
    
        checkForA();
    });