2014-08-31 82 views
1

我有這個遞歸函數,它給了我一些問題。它需要像20.000次那樣運行,但是當它多次循環瀏覽器崩潰時。任何幫助表示讚賞遞歸函數在多次循環時崩潰javascript

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

的功能需要的800毫秒默認的時間間隔,甚至更像是10分鐘內重複20.000倍

+0

等待的價值是什麼?我不會同時超過8個連接到同一個主機。由於您發佈的數據最好只有兩個連接。 – Wayne 2014-08-31 10:57:30

+0

等待時間以毫秒爲單位,由用戶設置。 8個連接?只有2個連接,它們必須分開 – 2014-08-31 11:00:47

+0

是否消耗大量內存? – Wayne 2014-08-31 11:08:24

回答

1

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

但是,您正在使用一個全局變量傳遞給一個函數,這將導致您作爲副本傳遞的範圍問題。通過將id傳入定時調用中,您將創建一個閉包,該閉包在20,000次時可能會導致一些問題。

+0

感謝您的輸入,我會嘗試使用相同的代碼而不使用id作爲參數,但不是遞歸函數是一個自稱的函數嗎? – 2014-08-31 12:49:54

+0

通過使用setTimeout,它不再真正調用自己了,頂級JavaScript引擎稍後調用它,函數中的執行繼續執行下一行,而不等待函數作爲setTimeout的一部分執行。這可能是您的整個問題(即在setTimeout 20,000次下執行所有處理,而不是尾遞歸)。 – 2014-08-31 12:51:52

+0

我可以看到你在說什麼,但沒有任何解決方案?我認爲JavaScript更強大。我現在嘗試沒有傳遞id值(這也解決了另一個問題哈哈)它現在循環。我希望它不會崩潰 – 2014-08-31 13:05:18

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> 
+0

你的代碼解決了什麼內存問題? – Bergi 2014-08-31 11:32:24

+0

@bergi我沒有看到內存問題的原因......特別尋找一個閉包,因爲函數在函數內部。但唯一的父活動是event.preventDefault();那甚至不能超過20,000個...... fetchMember每次都會關閉。 – Wayne 2014-08-31 11:37:52

+0

這是我之前的代碼,移動外部函數聲明時的問題是我無法訪問論壇提交時聲明的全局變量,例如其中一個是var time = $(this).find( 「#等待」)。val()* 1000; \t \t var wait =(time == 0)? 800:時間; – 2014-08-31 11:40:16

0

這就是你推入堆棧的20,000個函數調用。這非常耗費內存。

+0

每個都假設關閉。 – Wayne 2014-08-31 12:37:19

+0

@Wayne回答了標題,這是在搜索結果中顯示的問題 – djechlin 2014-08-31 12:39:32