簡體   English   中英

遞歸函數在多次循環時崩潰

[英]Recursive function crashes when it loops many times javascript

我有這個遞歸函數,這給了我一些問題。 它需要像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分鍾

此函數不是遞歸的,它只是使用setTimeout在將來的某個時刻再次調用自身,這與真正的遞歸不同。

但是,您正在使用傳遞給函數的全局變量,這將導致您在將問題作為副本傳遞時進行范圍界定。 通過將id傳遞給定時呼叫,您正在創建一個閉包,該閉包的次數為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;
        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>

這是您要壓入堆棧的20,000個函數調用。 那是非常占用內存的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM