简体   繁体   中英

Recursive function crashes when it loops many times javascript

I have this recursive function which is giving me some problems. It needs to be runned like 20.000 times, but when it loops many times the browser crashes. Any help is appreciated

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);
    });
});

The function needs to be repeated 20.000 times with a default interval of 800ms or even more like 10 minutes

This function isn't recursing, it's just using setTimeout to call itself again at some point in the future, which isn't the same as true recursion.

However, you're using a global variable passed into a function, this will be causing you scoping issues as it's passed as a copy. By passing the id in to the timed call, you're creating a closure, which at 20,000 times, may be causing you some issues.

Try if it is a memory issue but I don't see that looking at the code.

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);
                    });
                }
            });
        }

Memory leak references http://javascript.crockford.com/memory/leak.html ... jquery does not leak.

[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>

That's 20,000 function calls you're pushing onto the stack. That is very memory-intensive.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM