如何解决ie浏览器setTimeout问题?



我已经用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行。

基于Oriol响应/更新的代码
$(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

最新更新