Search code examples
jqueryvariablestimeoutdelay

While variable is not defined - wait


I have a click event that is triggered from another place automatically for the first time. My problem is that it runs too soon, since the required variables are still being defined by Flash and web services. So right now I have:

(function ($) {
    $(window).load(function(){
        setTimeout(function(){
            $('a.play').trigger("click");
        }, 5000);
    });
})(jQuery);

The problem is that 5 seconds for a person with a slow internet connection could be too fast and vice versa, for a person with a fast internet connection, it's too slow.

So how should I do the delay or timeout until someVariable is defined?


Solution

  • async, await implementation, improvement over @Toprak's answer

    (async() => {
        console.log("waiting for variable");
        while(!window.hasOwnProperty("myVar")) // define the condition as you like
            await new Promise(resolve => setTimeout(resolve, 1000));
        console.log("variable is defined");
    })();
    console.log("above code doesn't block main function stack");
    

    After revisiting the OP's question. There is actually a better way to implement what was intended: "variable set callback". Although the below code only works if the desired variable is encapsulated by an object (or window) instead of declared by let or var (I left the first answer because I was just doing improvement over existing answers without actually reading the original question):

    let obj = encapsulatedObject || window;
    Object.defineProperty(obj, "myVar", {
        configurable: true,
        set(v){
            Object.defineProperty(obj, "myVar", {
                configurable: true, enumerable: true, writable: true, value: v });
            console.log("window.myVar is defined");
        }
    });
        
    

    see Object.defineProperty or use es6 proxy (which is probably overkill)


    If you are looking for more:

    /**
     * combining the two as suggested by @Emmanuel Mahuni,
     * and showing an alternative to handle defineProperty setter and getter
     */
    
    
    let obj = {} || window;
    (async() => {
      let _foo = await new Promise(res => {
        Object.defineProperty(obj, "foo", { set: res });
      });
      console.log("obj.foo is defined with value:", _foo);
    })();
    /*
    IMPORTANT: note that obj.foo is still undefined
    the reason is out of scope of this question/answer
    take a research of Object.defineProperty to see more
    */
    
    // TEST CODE
    
    console.log("test start");
    setTimeout(async () => {
      console.log("about to assign obj.foo");
      obj.foo = "Hello World!";
      // try uncomment the following line and compare the output
      // await new Promise(res => setTimeout(res));
      console.log("finished assigning obj.foo");
      console.log("value of obj.foo:", obj.foo); // undefined
      // console: obj.foo is defined with value: Hello World!
    }, 2000);