当javascript循环很多次时递归函数崩溃

时间:2014-08-31 10:49:11

标签: javascript recursion

我有这个递归函数,它给了我一些问题。它需要像20.000次一样运行,但当它循环多次浏览器崩溃时。任何帮助表示赞赏

var valid = 0, id = 0;
$(document).ready(function() {
    $("#fetch").submit(function(event) {
        event.preventDefault();
        var selected = $(this).find("#site option:selected");
        var pieces = selected.text().split("(");
        var sitename = pieces[0];
        var numbers = pieces[1].slice(0,-1).split("/");
        var fetched = numbers[0]; var total = numbers[1];
        var members = $(this).find("#members").val();
        var time = $(this).find("#wait").val() * 1000;
        wait = (time == 0) ? 800 : time;
        $("progress").prop("value", 0).prop("max", members * 2).fadeIn();
        valid = 0;
        function fetchMember(id) {
            id++;
            $.post("script.php", $("#fetch").serialize() + "&id=" + id )
            .done(function(data) {
                console.clear();
                isUser = ($(data).text().indexOf("Invalid User") == -1);
                if (isUser) valid++;
                if(valid < members) setTimeout(function(){ fetchMember(id) }, wait);
                if (isUser) {
                    progress();
                    fetched++;
                    selected.text(sitename+"("+fetched+"/"+total+")"); //Updating numbers of fetched profiles on the frontend
                    username = $(data).find(".normal").text() || $(data).find(".member_username").text() || $(data).find("#username_box h1").text();
                    $(data).find("dt").each(function() {
                        var text = $(this).text();
                        if (text == 'Location') country = $(this).next("dd").text();
                    });
                    $.post("save.php", { username: username } )
                    .done(function(data) {
                        $("#test").append(id+" "+data + "<br />");
                        progress();
                    });
                }
            });
        }
        fetchMember(id);
    });
});

该功能需要重复20.000次,默认间隔为800ms,甚至更长,如10分钟

3 个答案:

答案 0 :(得分:1)

这个函数没有递归,它只是使用setTimeout在将来的某个时刻再次调用自身,这与真正的递归不同。

但是,您正在使用传递给函数的全局变量,这将导致您将范围问题作为副本传递。通过将id传递给定时调用,您将创建一个关闭,在20,000次,可能会导致一些问题。

答案 1 :(得分:0)

尝试是否存在内存问题,但我看不到代码。

var valid = 0, id = 0;
$(document).ready(function() {
    $("#fetch").submit(function(event) {
        event.preventDefault();
        var selected = $(this).find("#site option:selected");
        var pieces = selected.text().split("(");
        var sitename = pieces[0];
        var numbers = pieces[1].slice(0,-1).split("/");
        var fetched = numbers[0]; var total = numbers[1];
        var members = $(this).find("#members").val();
        var time = $(this).find("#wait").val() * 1000;
        wait = (time == 0) ? 800 : time;
        $("progress").prop("value", 0).prop("max", members * 2).fadeIn();
        valid = 0;
        fetchMember(id,selected,pieces,sitename,numbers,fetched,members,time,wait);
    });
});

function fetchMember(id,selected,pieces,sitename,numbers,fetched,members,time,wait) {
            id++;
            $.post("script.php", $("#fetch").serialize() + "&id=" + id )
            .done(function(data) {
                console.clear();
                isUser = ($(data).text().indexOf("Invalid User") == -1);
                if (isUser) valid++;

                if (isUser) {
                    progress();
                    fetched++;
                    selected.text(sitename+"("+fetched+"/"+total+")"); //Updating numbers of fetched profiles on the frontend
                    username = $(data).find(".normal").text() || $(data).find(".member_username").text() || $(data).find("#username_box h1").text();
                    $(data).find("dt").each(function() {
                        var text = $(this).text();
                        if (text == 'Location') country = $(this).next("dd").text();
                    });
                    $.post("save.php", { username: username } )
                    .done(function(data) {
                        $("#test").append(id+" "+data + "<br />");
                        progress();
                       if(valid < members) setTimeout(function(){ fetchMember(id,selected,pieces,sitename,numbers,fetched,members,time,wait) }, wait);
                    });
                }
            });
        }

内存泄漏引用http://javascript.crockford.com/memory/leak.html ... jquery不泄漏。

[Exhibit 4 - Leak test with a closure]

<html>
<head>
<script type="text/javascript">
    function LeakMemory(){
        var parentDiv = document.createElement("div");
                          parentDiv.onclick=function(){
            foo();
        };

        parentDiv.bigString = 
          new Array(1000).join(new Array(2000).join("XXXXX"));
    }
</script>
</head>
<body>
<input type="button" 
       value="Memory Leaking Insert" onclick="LeakMemory()" />
</body>
</html>

答案 2 :(得分:0)

那个20,000函数调用你正在推动堆栈。这是非常耗费内存的。