web-dev-qa-db-ja.com

変数が定義されていない間-待機

別の場所から初めて自動的にトリガーされるclickイベントがあります。私の問題は、必要な変数がFlashとWebサービスによってまだ定義されているため、実行が早すぎることです。だから今、私は持っています:

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

問題は、インターネット接続が遅い人の場合、5秒は速すぎる可能性があり、逆もまた同様です。インターネット接続が速い人の場合、遅すぎるのです。

someVariableが定義されるまで、どのように遅延またはタイムアウトを行う必要がありますか?

45
JackLeo

私はこのコードを好むでしょう:

function checkVariable() {

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

 setTimeout(checkVariable, 1000);
21
Tushar Ahirrao

以下は、見つかるまでsomeVariableを探し続けます。 0.25秒ごとにチェックします。

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

Ecma Script 2017では、async-awaitとwhileを一緒に使用してそれを行うことができますが、プログラムがクラッシュしたりロックしたりすることはありません

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

また、この場合はsetTimeoutを使用する必要はありません。ready関数を非同期にするだけです...

6
Toprak

async, await実装、 @ 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");

OPの質問を再検討した後。実際には、意図したものを実装するためのより良い方法があります:「変数セットコールバック」。以下のコードは、目的の変数がletまたはvarによって宣言されているのではなく、オブジェクト(またはウィンドウ)によってカプセル化されている場合にのみ機能します(実際に元の質問を読まずに答えます):

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

Object.defineProperty を参照するか、または es6プロキシ を使用します(これはおそらくやり過ぎです)

4
Valen

変数が設定されるまで待機するすべてのロジックが、プログラムが必要とする他のすべてを実行するコールバックを呼び出す関数に委ねられる例を次に示します-他のことを行う前に変数をロードする必要がある場合、これはきちんと感じます-それを行うための方法ですので、変数ロードを他のすべてから分離していますが、「他のすべて」が本質的にコールバックであることを保証しています。

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

より短い方法:

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

引数を渡すこともできます

2
tdmartin

これを使用できます:

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

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

Windowsのloadイベントを使用する代わりに、ドキュメントでreadyイベントを使用します。

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

これは、完全にロードされたメディアコンテンツを含む、DOM内のすべての準備が整ったときに起動します。

2
Jamie Dixon

完了したら、Flashで関数を呼び出すことができます。 Webサービスの意味がわかりません。 Ajaxを介してWebサービスを呼び出すJavaScriptコードがあると仮定します。この場合、いつ終了するかがわかります。最悪の場合、100msごとにチェックするループsetTimeoutを実行できます。

そして、変数が定義されているかどうかのチェックは、単にif (myVariable)またはそれより安全です:if(typeof myVariable == "undefined")

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

または、このプロパティを関数への引数として渡すだけで、グローバルオブジェクトで定義する必要がない場合でも:

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

ただし、この例ではノードの作成時にアクションを実行するように見えるため、 MutationObservers を確認することをお勧めします。

0
Przemek

私は@dnuttleの answer に賛成しましたが、次の戦略を使用することになりました。

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

テスト済みで動作しています! ;)

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

0