我已经用setTimeout在一些编码上工作了几天,它在我的主要测试浏览器Chrome上工作。有一次我在不同的浏览器上检查了这个功能,ie浏览器给了我一个问题,根本无法工作。其他浏览器也可以。
$(childWindow).load(function()
{
var dateObject = new Date();
var startTime = Date.now() + (dateObject.getTimezoneOffset() - 300) * 60000; // GMT -5
var currentTime = startTime();
var counter = 0;
var runningFunction = function()
{
var remainingTime = Math.round((startTime + 10 * 1000 - (Date.now() + (dateObject.getTimezoneOffset() - 300) * 60000)) / 1000);
if (remainingTime > 0)
{
// update timer in HTML which is not shown
currentTime = Date.now() + (dateObject.getTimezoneOffset() - 300) * 60000;
var nextCounter = 100 - (currentTime - (startTime + (counter * 100))); // compensate for browser drifting
counter++;
childWindow.setTimeout(runningFunction, nextCounter); // try to update nearly at 100 milliseconds every 100 milliseconds
}
};
childWindow.setTimeout(runningFunction, 100); // initially update at 100 milliseconds
// other jQuery coding used
});
这只是代码的一部分,但我认为问题就在这里。一些逻辑或语法可能是不正确的,但这不是我的问题。在10秒后,不应该有setTimeout调用,因为remainingTime将是负的,所以没有真正的"无限循环"。有了这个(部分)代码,它在Chrome中完美地工作,每100毫秒执行一次。在ie浏览器中,什么都不会发生。我在其他Stack Overflow帖子和其他外部资源上读到语法应该是setTimeout(function() { calleeFunction(); }, time);
我尝试将var runningFunction = function()
更改为function runningFunction()
和setTimeout
功能部分更改为function() { runningFunction(); }
,这确实有效,但完全挂在Chrome和Internet Explorer中最终导致一些堆栈错误(我认为这是IE中的脚本28)在10秒"无限"setTimeout
调用循环。
我尝试的另一个解决方案是var runningFunction = (function() { ... }());
,但这一行在childWindow.setTimeout(runningFunction, 100);
行之前执行。我希望变量只是声明,但不执行,直到childWindow.setTimeout
行被调用。我不介意把匿名函数放在setTimeout
函数中,但我实际上是在程序的其他部分使用这一行来重新启动计时器,函数本身超过200行,所以我不想在程序的多个部分复制相同的200行。
$(childWindow).load(function()
{
$.post("x.php", { a: "", b: "", c: "" }, function(data)
{
if (data !== "")
$("div:first", childWindow.document).html(data);
else
{
var dateObject = new Date(),
startTime = aux(),
currentTime,
counter = 0;
function aux() {
return +new Date() + (dateObject.getTimezoneOffset() - 300) * 6e4;
}
function runningFunction()
{
console.log('runningFunction');
var currentAux = aux(),
remainingTime = Math.round( 10 + (startTime - currentAux) / 1e3 );
if (remainingTime > 0)
{
$("div:first", childWindow.document).html("<div>" + remainingTime + "</div>");
currentTime = currentAux;
var nextCounter = Math.max(0, 100 - currentTime + startTime + counter * 100);
// compensate for browser drifting
counter++;
childWindow.setTimeout(runningFunction, nextCounter);
// try to update nearly at 100 milliseconds every 100 milliseconds
}
}
$("div:first", childWindow.document).html("<div>Random message.</div>");
if (childWindow.document.hasFocus() && childWindow.outerWidth >= 0.90 * screen.availWidth && childWindow.outerHeight >= 0.90 * screen.availHeight)
{
var pauseTime = "";
var running = true;
childWindow.setTimeout(runningFunction, 100);
}
else
{
var pauseTime = startTime;
var running = false;
}
}
});
});
提供的小提琴确实工作,但它不能在网站上工作。基于这种编码,setTimeout
不会被执行的唯一方式是如果最后一个if语句块为false。我在true语句中放置了一个console.log消息,它确实返回了该消息,所以我知道IE正在执行该块,因此它必须到达setTimeout
行。再一次,用这种编码,同样的情况发生,因为它最初发布,Chrome显示console.log消息在函数中每~100毫秒,IE甚至不考虑函数。我真是走到死胡同了。
你的代码有一些问题:
- 语法错误
- 在IE9之前没有
Date.now()
支持。你可以使用+new Date()
- 大多数时候
nextCounter
是负的,所以延迟函数不能在IE上运行。您可以使用Math.max(0, nextCounter)
。
如此:
var dateObject = new Date(),
startTime = aux(),
currentTime,
counter = 0;
function aux() {
return +new Date() + (dateObject.getTimezoneOffset() - 300) * 6e4;
}
function runningFunction()
{
console.log('runningFunction');
var currentAux = aux(),
remainingTime = Math.round( 10 + (startTime - currentAux) / 1e3 );
if (remainingTime > 0)
{
// update timer in HTML which is not shown
currentTime = currentAux;
var nextCounter = Math.max(0, 100 - currentTime + startTime + counter * 100);
// compensate for browser drifting
counter++;
childWindow.setTimeout(runningFunction, nextCounter);
// try to update nearly at 100 milliseconds every 100 milliseconds
}
};
childWindow.setTimeout(runningFunction, 100);
// initially update at 100 milliseconds