1

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

12
  • What is the value of wait? And I would not exceed 8 connections at the same time to the same host. Since you are posting data it may be best to only have two connections. Commented Aug 31, 2014 at 10:57
  • wait is time in ms, it's set by the user. 8 connections? There are only 2 connections and they must be separated Commented Aug 31, 2014 at 11:00
  • Is it consuming vast amounts of memory? Commented Aug 31, 2014 at 11:08
  • I don't see anything that would cause a memory leak but the solution to a memory leak would be place fetchMember(id) as a global function not as a nested function. Commented Aug 31, 2014 at 11:10
  • Thank you, how would I go for that? I never faced these memory problems, so I wouldn't know. The first page, script.php, is using curl connection to login to an external website, and printing protected page content. I don't think that would cause many problems on the client side though Commented Aug 31, 2014 at 11:25

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for your input, I'll try the same code without using id as a parameter, however isn't a recursive function a function that call itself?
By using setTimeout it isn't really calling itself anymore, the top-level JavaScript engine is calling it at a later time, the execution in the function continues to the next lines without waiting for the function as part of the setTimeout to execute. This could be your entire problem (i.e. doing all that processing under the setTimeout 20,000 times rather than a tail recursion).
I can see what you're saying but there isn't any solution to this? I thought javascript was more powerful. I'm trying now without passing the id value (this also solved another problem lol) it's now looping. I hope it won't crash
JavaScript is incredibly powerful, if I had full access to what you were trying to do, I'm sure the solution would jump out at me, but it's hard to say here. If you could get it working in a jsfiddle.net demo, I could debug it.
Thanks for your help really, it's still executing the script. My finger are crossed. If I still have problems I'll let you know. Unfortunately sometimes it's hard to reproduce the same problem on jsfiddle. If you have some time to look at it and you have XAMPP or MAMP installed I can send you the project in an email, thanks anyway for your help
|
0

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

2 Comments

Each is suppose to close.
@Wayne answered the title, which is the question that shows up in search results
0

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>

3 Comments

@bergi I don't see a cause for a memory issue ... specifically looking for a closure as the function is inside a function. but the only parent activity is event.preventDefault(); that can not be that much even 20,000 of them ... fetchMember closes each time.
This was my code before, the problem when moving the function declaration outside is that I can't access anymore to the global variables declared when the forum is submitted, for example one of these are var time = $(this).find("#wait").val() * 1000; var wait = (time == 0) ? 800 : time;
Thank you I'll update the question with the full code, because I don't fully understand your answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.