首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >jquery setTimeout过多的递归

jquery setTimeout过多的递归
EN

Stack Overflow用户
提问于 2015-05-25 18:36:58
回答 1查看 1.1K关注 0票数 1

我从多个地方读到,当设置一些基本永久运行的东西时,setTimeout()比setInterval()更可取。下面的代码运行良好,但运行了大约一个小时后(38.0.1)抛出了too much recursion错误。

本质上,我让它从counts.php抓取少量文本,并使用该信息更新表。根据检验员的说法,整个通话和回程大约需要50毫秒。我正试着让它按照t的指示每x秒做一次。

我怀疑如果切换到setInterval(),这可能会有效,但我不确定setTimeout()与setInterval()思维的当前状态是什么,因为我发现的所有东西都在3-5岁左右。

代码语言:javascript
复制
$(document).ready(function() {
    t = 3000;
    $.ajaxSetup({cache: false});

     function countsTimer(t) {
        setTimeout(function () {
            $.getJSON("counts.php", function (r) {
                $(".count").each(function(i,v) {
                    if ($(this).html() != r[i]) {
                        $(this).fadeOut(function () {
                            $(this)
                                .css("color", ($(this).html() < r[i]) ? "green" : "red")
                                .html(r[i])
                                .fadeIn()
                                .animate({color: '#585858'}, 10000);
                        })
                    };
                });

                t = $(".selected").html().slice(0,-1) * ($(".selected").html().slice(-1) == "s" ? 1000 : 60000);

                countsTimer(t);
            });
        }, t);
    };
    countsTimer(t);
});

更新:通过在.fadeOut()动画之前添加.stop(真,真)解决了这个问题。此问题仅在Firefox中发生,因为在其他浏览器中进行测试不会引起任何问题。我认为答案是正确的,尽管它不是这个特殊情况下的解决办法,而是提供了一个更一般意义上的很好的解释。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-25 19:17:27

在这种情况下,您确实应该切换到setInterval()。setInterval()的问题是,如果要清除超时,则必须保留引用,如果操作(可能)比超时本身执行的时间更长,则操作可能会运行两次。

例如,如果一个函数使用setInterval每1s运行一次,但是由于XHR请求较慢,该函数本身需要2s才能完成,该函数在某个时候将同时运行两次。这往往是不可取的。通过使用setTimout并调用原始函数的末尾,函数永不重叠,所设置的超时始终是两个函数调用之间的时间。

但是,在您的情况下,您的应用程序运行时间似乎很长,因为您的函数每3秒运行一次,函数调用堆栈将每3秒增加一个。除非您中断这个递归循环,否则这是无法避免的。例如,只有在收到浏览器事件(如单击文档和检查时间)时,才能执行请求。

代码语言:javascript
复制
(function() 
{
    var lastCheck = Date.now(), alreadyRunning = false;
    document.addEventListener
    (
        "click", 
        function() 
        {
            if(!alreadyRunning && Date.now() - lastCheck > 3000) 
            {
                alreadyRunning = true;
                /* Do your request here! */
                //Code below should run after your request has finished
                lastCheck = Date.now();
                alreadyRunning = false;
            }
        }
    )
}());

这没有setInterval的缺点,因为您总是检查代码是否已经运行,但是只有在接收到浏览器事件时才会运行检查。(这通常不是问题。)这种方法会产生更多的样板。

因此,如果您确信XHR请求的完成时间不会超过3s,只需使用setInterval()即可。

编辑:上面的答案在某些方面是错误的,

正如注释中指出的那样,setTimeout()确实没有增加调用堆栈的大小,因为它在调用超时中的函数之前返回。此外,问题中的函数不包含任何特定的递归。我将保留这个答案,因为问题的一部分是关于setTimeout()和setInterval()。但是,导致递归错误的问题可能出现在其他代码中,因为在示例代码中的任何地方都没有函数直接或间接地调用自己。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30444224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档