如何解决Internet Explorer setTimeout问题?

时间:2014-06-05 17:28:49

标签: javascript internet-explorer

我已经在一些编码上使用了setTimeout几天,它在我的主要测试浏览器Chrome上工作。一旦我在不同的浏览器上检查了该功能,Internet Explorer就给了我一个问题,根本没用。其他浏览器也有效。

$(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毫秒执行一次。在Internet Explorer中,根本没有任何事情发生。我读了其他Stack Overflow帖子和其他外部资源,语法应该是setTimeout(function() { calleeFunction(); }, time);

我尝试将var runningFunction = function()更改为function runningFunction(),将setTimeout功能部分更改为function() { runningFunction(); },该功能可以正常工作,但在Chrome和Internet Explorer中完全挂起,最终导致一些堆栈错误(在10秒“无限”setTimeout调用循环期间,我认为这是IE中的脚本28。

我尝试的另一个解决方案是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每隔约100毫秒在函数中显示console.log消息,IE甚至根本不考虑该功能。我真的跑到了死胡同。

1 个答案:

答案 0 :(得分:0)

您的代码存在一些问题:

  • 语法错误
  • 直到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

Demo