我有一个click
事件,这是第一次自动从另一个地方触发。我的问题是它运行得太快,因为Flash和Web服务仍然定义了所需的变量。所以现在我有:
(function ($) {
$(window).load(function(){
setTimeout(function(){
$('a.play').trigger("click");
}, 5000);
});
})(jQuery);
问题是,互联网连接速度慢的人可能需要5秒钟,反之亦然,对于网速较快的人来说,速度太慢。
那么在定义someVariable
之前我应该怎么做延迟或超时?
答案 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。