While variable is not defined - wait

拜拜、爱过 提交于 2019-11-27 13:24:38

问题


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?


回答1:


I would prefer this code:

function checkVariable() {

   if (variableLoaded == true) {
       // Here is your next action
   }
 }

 setTimeout(checkVariable, 1000);



回答2:


The following will keep looking for someVariable until it is found. It checks every 0.25 seconds.

function waitForElement(){
    if(typeof someVariable !== "undefined"){
        //variable exists, do what you want
    }
    else{
        setTimeout(waitForElement, 250);
    }
}



回答3:


With Ecma Script 2017 You can use async-await and while together to do that And while will not crash or lock the program even variable never be true

//First define some delay function which is called from async function
function __delay__(timer) {
    return new Promise(resolve => {
        timer = timer || 2000;
        setTimeout(function () {
            resolve();
        }, timer);
    });
};

//Then Declare Some Variable Global or In Scope
//Depends on you
let Variable = false;

//And define what ever you want with async fuction
async function some() {
    while (!Variable)
        await __delay__(1000);

    //...code here because when Variable = true this function will
};
////////////////////////////////////////////////////////////
//In Your Case
//1.Define Global Variable For Check Statement
//2.Convert function to async like below

var isContinue = false;
setTimeout(async function () {
    //STOPT THE FUNCTION UNTIL CONDITION IS CORRECT
    while (!isContinue)
        await __delay__(1000);

    //WHEN CONDITION IS CORRECT THEN TRIGGER WILL CLICKED
    $('a.play').trigger("click");
}, 1);
/////////////////////////////////////////////////////////////

Also you don't have to use setTimeout in this case just make ready function asynchronous...




回答4:


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)




回答5:


Here's an example where all the logic for waiting until the variable is set gets deferred to a function which then invokes a callback that does everything else the program needs to do - if you need to load variables before doing anything else, this feels like a neat-ish way to do it, so you're separating the variable loading from everything else, while still ensuring 'everything else' is essentially a callback.

var loadUser = function(everythingElse){
    var interval = setInterval(function(){
      if(typeof CurrentUser.name !== 'undefined'){
        $scope.username = CurrentUser.name;
        clearInterval(interval);
        everythingElse();
      }
    },1);
  };

  loadUser(function(){

    //everything else

  });



回答6:


Instead of using the windows load event use the ready event on the document.

$(document).ready(function(){[...]});

This should fire when everything in the DOM is ready to go, including media content fully loaded.




回答7:


You can use this:

var refreshIntervalId = null;
refreshIntervalId = setInterval(checkIfVariableIsSet, 1000);

var checkIfVariableIsSet = function()
{
    if(typeof someVariable !== 'undefined'){
        $('a.play').trigger("click");
        clearInterval(refreshIntervalId);
    }
};



回答8:


Shorter way:

   var queue = function (args){
      typeof variableToCheck !== "undefined"? doSomething(args) : setTimeout(function () {queue(args)}, 2000);
};

You can also pass arguments




回答9:


You could have Flash call the function when it's done. I'm not sure what you mean by web services. I assume you have JavaScript code calling web services via Ajax, in which case you would know when they terminate. In the worst case, you could do a looping setTimeout that would check every 100 ms or so.

And the check for whether or not a variable is defined can be just if (myVariable) or safer: if(typeof myVariable == "undefined")




回答10:


I have upvoted @dnuttle's answer, but ended up using the following strategy:

// On doc ready for modern browsers
document.addEventListener('DOMContentLoaded', (e) => {
  // Scope all logic related to what you want to achieve by using a function
  const waitForMyFunction = () => {
    // Use a timeout id to identify your process and purge it when it's no longer needed
    let timeoutID;
    // Check if your function is defined, in this case by checking its type
    if (typeof myFunction === 'function') {
      // We no longer need to wait, purge the timeout id
      window.clearTimeout(timeoutID);
      // 'myFunction' is defined, invoke it with parameters, if any
      myFunction('param1', 'param2');
    } else {
      // 'myFunction' is undefined, try again in 0.25 secs
      timeoutID = window.setTimeout(waitForMyFunction, 250);
    }
  };
  // Initialize
  waitForMyFunction();
});

It is tested and working! ;)

Gist: https://gist.github.com/dreamyguy/f319f0b2bffb1f812cf8b7cae4abb47c




回答11:


Object.defineProperty(window, 'propertyName', {
    set: value => {
        this._value = value;
        // someAction();
    },
    get: () => this._value
});

or even if you just want this property to be passed as an argument to a function and don't need it to be defined on a global object:

Object.defineProperty(window, 'propertyName', { set: value => someAction(value) })

However, since in your example you seem to want to perform an action upon creation of a node, I would suggest you take a look at MutationObservers.



来源:https://stackoverflow.com/questions/7307983/while-variable-is-not-defined-wait

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!