別の場所から初めて自動的にトリガーされるclick
イベントがあります。私の問題は、必要な変数がFlashとWebサービスによってまだ定義されているため、実行が早すぎることです。だから今、私は持っています:
(function ($) {
$(window).load(function(){
setTimeout(function(){
$('a.play').trigger("click");
}, 5000);
});
})(jQuery);
問題は、インターネット接続が遅い人の場合、5秒は速すぎる可能性があり、逆もまた同様です。インターネット接続が速い人の場合、遅すぎるのです。
someVariable
が定義されるまで、どのように遅延またはタイムアウトを行う必要がありますか?
私はこのコードを好むでしょう:
function checkVariable() {
if (variableLoaded == true) {
// Here is your next action
}
}
setTimeout(checkVariable, 1000);
以下は、見つかるまでsomeVariableを探し続けます。 0.25秒ごとにチェックします。
function waitForElement(){
if(typeof someVariable !== "undefined"){
//variable exists, do what you want
}
else{
setTimeout(waitForElement, 250);
}
}
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関数を非同期にするだけです...
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プロキシ を使用します(これはおそらくやり過ぎです)
変数が設定されるまで待機するすべてのロジックが、プログラムが必要とする他のすべてを実行するコールバックを呼び出す関数に委ねられる例を次に示します-他のことを行う前に変数をロードする必要がある場合、これはきちんと感じます-それを行うための方法ですので、変数ロードを他のすべてから分離していますが、「他のすべて」が本質的にコールバックであることを保証しています。
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
});
より短い方法:
var queue = function (args){
typeof variableToCheck !== "undefined"? doSomething(args) : setTimeout(function () {queue(args)}, 2000);
};
引数を渡すこともできます
これを使用できます:
var refreshIntervalId = null;
refreshIntervalId = setInterval(checkIfVariableIsSet, 1000);
var checkIfVariableIsSet = function()
{
if(typeof someVariable !== 'undefined'){
$('a.play').trigger("click");
clearInterval(refreshIntervalId);
}
};
Windowsのloadイベントを使用する代わりに、ドキュメントでreadyイベントを使用します。
$(document).ready(function(){[...]});
これは、完全にロードされたメディアコンテンツを含む、DOM内のすべての準備が整ったときに起動します。
完了したら、Flashで関数を呼び出すことができます。 Webサービスの意味がわかりません。 Ajaxを介してWebサービスを呼び出すJavaScriptコードがあると仮定します。この場合、いつ終了するかがわかります。最悪の場合、100msごとにチェックするループsetTimeout
を実行できます。
そして、変数が定義されているかどうかのチェックは、単にif (myVariable)
またはそれより安全です:if(typeof myVariable == "undefined")
Object.defineProperty(window, 'propertyName', {
set: value => {
this._value = value;
// someAction();
},
get: () => this._value
});
または、このプロパティを関数への引数として渡すだけで、グローバルオブジェクトで定義する必要がない場合でも:
Object.defineProperty(window, 'propertyName', { set: value => someAction(value) })
ただし、この例ではノードの作成時にアクションを実行するように見えるため、 MutationObservers を確認することをお勧めします。
私は@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