虽然未定义变量 - 等待

时间:2011-09-05 12:19:42

标签: jquery variables timeout delay

我有一个click事件,这是第一次自动从另一个地方触发。我的问题是它运行得太快,因为Flash和Web服务仍然定义了所需的变量。所以现在我有:

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

问题是,互联网连接速度慢的人可能需要5秒钟,反之亦然,对于网速较快的人来说,速度太慢。

那么在定义someVariable之前我应该​​怎么做延迟或超时?

15 个答案:

答案 0 :(得分:88)

以下内容将继续寻找someVariable,直到找到它为止。它每0.25秒检查一次。

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

答案 1 :(得分:21)

我更喜欢这段代码:

function checkVariable() {

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

 setTimeout(checkVariable, 1000);

答案 2 :(得分:6)

使用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,只需将就绪函数设为异步...

答案 3 :(得分:4)

我喜欢这样简单的东西:

function waitFor(variable, callback) {
  var interval = setInterval(function() {
    if (window[variable]) {
      clearInterval(interval);
      callback();
    }
  }, 200);
}

然后将其与示例变量someVariable一起使用:

waitFor('someVariable', function() {
  // do something here now that someVariable is defined
});

请注意,您可以进行多种调整。在上面的setInterval调用中,我通过了200作为间隔函数应该运行的频率。在检查变量之前,该时间还存在一个固有的延迟(约200毫秒)-在某些情况下,最好立即进行检查以确保没有延迟。

答案 4 :(得分:3)

不使用Windows加载事件,而是在文档上使用ready事件。

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

当DOM中的所有内容都准备就绪时,这应该触发,包括完全加载的媒体内容。

答案 5 :(得分:3)

这是一个例子,其中等待设置变量的所有逻辑都被延迟到一个函数,然后调用一个回调来执行程序需要做的其他事情 - 如果你需要在做任何其他事情之前加载变量,这感觉就像一个干净利落的方式,所以你将变量加载与其他一切分开,同时仍然确保“其他一切”基本上都是一个回调。

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 :(得分:2)

您可以使用:

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

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

答案 7 :(得分:2)

缩短方式:

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

您也可以传递参数

答案 8 :(得分:2)

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

答案 9 :(得分:0)

完成后,您可以让Flash调用该函数。我不确定你的网络服务是什么意思。我假设您有通过Ajax调用Web服务的JavaScript代码,在这种情况下,您将知道它们何时终止。在最坏的情况下,您可以执行循环setTimeout,每100 ms左右检查一次。

检查变量是否定义可以只是if (myVariable)或更安全:if(typeof myVariable == "undefined")

答案 10 :(得分:0)

我赞成@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

答案 11 :(得分:0)

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

,或者即使您只是希望将此属性作为参数传递给函数,也不需要在全局对象上定义它:

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

但是,由于在您的示例中您似乎想在创建节点时执行操作,因此建议您看看MutationObservers

答案 12 :(得分:0)

到晚会很晚,但是我想为所有将来关注此问题的开发人员提供更现代的解决方案。它基于Toprak的答案,但经过简化以使其更清楚地显示正在发生的事情。

<div>Result: <span id="result"></span></div>

<script>
    var output = null;
    
    // Define an asynchronous function which will not block where it is called.
    async function test(){
        // Create a promise with the await operator which instructs the async function to wait for the promise to complete.
        await new Promise(function(resolve, reject){
            // Execute the code that needs to be completed.
            // In this case it is a timeout that takes 2 seconds before returning a result. 
            setTimeout(function(){
                // Just call resolve() with the result wherever the code completes.
                resolve("success output");
            }, 2000);
            
            // Just for reference, an 'error' has been included.
            // It has a chance to occur before resolve() is called in this case, but normally it would only be used when your code fails.
            setTimeout(function(){
                // Use reject() if your code isn't successful.
                reject("error output");
            }, Math.random() * 4000);
        })
        .then(function(result){ 
            // The result variable comes from the first argument of resolve().
            output = result; 
        })
        .catch(function(error){ 
            // The error variable comes from the first argument of reject().
            // Catch will also catch any unexpected errors that occur during execution.
            // In this case, the output variable will be set to either of those results.
            if (error) output = error; 
        });
        
        // Set the content of the result span to output after the promise returns.
        document.querySelector("#result").innerHTML = output;
    }
    
    // Execute the test async function.
    test();

    // Executes immediately after test is called.
    document.querySelector("#result").innerHTML = "nothing yet";
</script>

这里的代码没有注释,以便于视觉理解。

var output = null;

async function test(){
    await new Promise(function(resolve, reject){
        setTimeout(function(){
            resolve("success output");
        }, 2000);

        setTimeout(function(){
            reject("error output");
        }, Math.random() * 4000);
    })
    .then(function(result){ 
        output = result; 
    })
    .catch(function(error){ 
        if (error) output = error; 
    });

    document.querySelector("#result").innerHTML = output;
}

test();

document.querySelector("#result").innerHTML = "nothing yet";

最后一点,according to MDN,所有现代浏览器都支持Promises,唯一的例外是Internet Explorer。此兼容性信息也是supported by caniuse。但是,随着Bootstrap 5放弃对Internet Explorer的支持以及基于webkit的新Edge,对于大多数开发人员来说,这不太可能成为问题。

答案 13 :(得分:0)

我建议使用@dnuttle 的答案改编版。

使用 try-catch 块的优点是,如果您尝试执行的代码的任何部分失败,整个块都会失败。我发现这很有用,因为它为您提供了一种交易;一事无成,一事无成。

您永远不应该编写可能因外部因素而陷入无限循环的代码。如果您正在等待来自 ajax 请求的响应而服务器没有响应,就会发生这种情况'回复。我认为对任何有问题的循环设置超时是一种很好的做法。

let time = 0; // Used to keep track of how long the loop runs
function waitForElement() {
  try {
    // I'm testing for an element, but this condition can be
    // any reasonable condition
    if (document.getElementById('test') === null) {
      throw 'error';
    }

    // This is where you can do something with your variable
    // document.getElementById('test').addEventListener....
    // or call a function that uses your value

  } catch (error) {
    // Loop stops executing if not successful within about 5 seconds
    if (time > 5000) {
      // I return false on failure so I can easily check for failure
      return false;
    } else {
      // Increment the time and call the function again
      time += 250;
      setTimeout(waitForElement, 250);
    }
  }
}

// Call the function after the definition, ensures that time is set
waitForElement();

答案 14 :(得分:-1)

import { LoginComponent } from "app/components/login/login.component"

export class ContractFormComponent implements OnInit {

  loginComponent: LoginComponent

  constructor( private _login: LoginComponent ) {
    this.loginComponent = _login;
  }

  callAnythingFromLoginComponent() {
    this.loginComponent.anyFunctionFromLoginComponent();
  }
}

这利用了 typeof 运算符,如果变量尚未声明,则该运算符仅返回 undefined。应该适用于所有类型的 javascript。