webentwicklung-frage-antwort-db.com.de

Während die Variable nicht definiert ist - warten

Ich habe ein click-Ereignis, das zum ersten Mal automatisch von einer anderen Stelle ausgelöst wird. Mein Problem ist, dass es zu früh läuft, da die erforderlichen Variablen immer noch von Flash und Webservices definiert werden. So jetzt habe ich:

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

Das Problem ist, dass 5 Sekunden für eine Person mit einer langsamen Internetverbindung zu schnell sein könnten und umgekehrt, für eine Person mit einer schnellen Internetverbindung ist es zu langsam.

Wie soll ich also die Verzögerung oder das Timeout durchführen, bis someVariable definiert ist?

40
JackLeo

Ich würde diesen Code vorziehen:

function checkVariable() {

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

 setTimeout(checkVariable, 1000);
17
Tushar Ahirrao

Im Folgenden wird nach someVariable gesucht, bis es gefunden wird. Es wird alle 0,25 Sekunden geprüft.

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

async, await Implementierung, Verbesserung gegenüber @ Toprak Antwort

(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");

Nach erneuter Prüfung der Frage des OP. Es gibt tatsächlich eine bessere Möglichkeit, das zu implementieren, was beabsichtigt war: "Variablen-Set-Callback". Obwohl der folgende Code nur funktioniert, wenn die gewünschte Variable von einem Objekt (oder einem Fenster) eingekapselt wird, anstatt von let oder var deklariert zu werden (ich habe die erste Antwort hinterlassen, weil ich gerade eine Verbesserung gegenüber der vorhandenen vorgenommen habe Antworten, ohne die ursprüngliche Frage tatsächlich zu lesen):

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");
    }
});

siehe Object.defineProperty oder benutze es6 proxy (was wahrscheinlich übertrieben ist)

4
Valen

Hier ein Beispiel, bei dem die gesamte Logik für das Warten, bis die Variable gesetzt ist, auf eine Funktion verschoben wird, die dann einen Rückruf aufruft, der alles andere tut, was das Programm tun muss Auf diese Weise trennen Sie das Laden der Variablen von allem anderen und stellen gleichzeitig sicher, dass "alles andere" im Wesentlichen ein Rückruf ist.

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

  });
3
Ollie H-M

Verwenden Sie anstelle des Windows-Ladeereignisses das Ready-Ereignis für das Dokument.

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

Dies sollte ausgelöst werden, wenn alles im DOM einsatzbereit ist, einschließlich vollständig geladener Medieninhalte.

3
Jamie Dixon

Mit Ecma Script 2017 können Sie async-await und, während dies zusammen ausgeführt wird, verwenden Und während die Programmvariable nicht abstürzt oder gesperrt wird, ist sie niemals wahr

//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);
/////////////////////////////////////////////////////////////

In diesem Fall müssen Sie setTimeout nicht verwenden, sondern nur die asynchrone Funktion ...

2
Toprak

Kürzerer Weg:

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

Sie können auch Argumente übergeben

2
tdmartin

Sie können dies verwenden:

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

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

Sie könnten Flash dazu bringen, die Funktion aufzurufen, wenn sie fertig ist. Ich bin mir nicht sicher, was Sie mit Webservices meinen. Ich gehe davon aus, dass Sie JavaScript-Code haben, der Web-Services über Ajax aufruft. In diesem Fall wissen Sie, wann sie beendet werden. Im schlimmsten Fall können Sie einen Schleifen setTimeout ausführen, der alle 100 ms überprüft wird.

Die Prüfung, ob eine Variable definiert ist oder nicht, kann nur if (myVariable) oder sicherer sein: if(typeof myVariable == "undefined")

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

oder auch, wenn diese Eigenschaft nur als Argument an eine Funktion übergeben werden soll und nicht für ein globales Objekt definiert werden muss:

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

Da Sie in Ihrem Beispiel jedoch scheinbar beim Erstellen eines Knotens eine Aktion ausführen möchten, würde ich Ihnen vorschlagen, einen Blick auf MutationObservers .

0
Przemek

Ich habe @ dnuttle's answer auf den neuesten Stand gebracht, aber am Ende habe ich folgende Strategie angewandt:

// 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();
});

Es ist getestet und funktioniert! ;)

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

0