2015-02-08 179 views
0

我想在循環中檢查列表中的3000個項目。在每一步我必須在頁面上進行異步httprequest。使之成爲一個遞歸函數IST扔InternalError: too much recursion 這是到目前爲止我的代碼:JavaScript異步調用循環

var iteratorObject = new function(){ 
    this.currentStep = -1; 
    this.iterationList = {}; 

    this.start = function(list){ 
     this.iterationList = list; 
     this.next(0); 
    } 

    this.next = function(value) { 
     this.currentStep = value; 
     if(this.currentStep +1 == this.iterationList.length){ 
      return 
     } 
     var currentID = this.iterationList[this.currentStep]; 

     //Do Aysnc HttpRequest on succeed call this.next(value +1); 
    } 

} 

var iterator = iteratorObject; 
var iterationList = Object.keys([Object]); 
    iterator.start(iterationList); 

如何更改我的代碼以避免遞歸函數,只有一次處理一個請求?

+0

你不能在'for'循環,除非你想要寫一個框架,做_promises_做到這一點。你看起來像你很接近 - 只需重寫'next',以便查看'currentStep'而不需要'value'。 – 2015-02-09 00:02:00

+0

在回調中調用下一個仍然是遞歸函數?我有一種方法可以在currentStep上調用next()函數來獲取事件列表。 對不起,我有點雛在JS – 2015-02-09 00:06:23

+0

你可以看看這個jsbin我準備:http://jsbin.com/kacabu/1/edit?js,console – 2015-02-09 00:47:17

回答

0

我想補充另一種解決方案,我認爲這是一個有趣的問題,所以這裏的東西我熟了基於原來的解決方案:

function Iterator(doWork) { 
    var done, start; 

    done = function() { 
     start(); 
    }; 

    start = function() { 
     doWork(done); 
    }; 

    // Export this method. 
    this.start = start; 
} 

和使用是:

<ul id="times"> 
    Iterations... 
</ul> 

<script type="text/javascript"> 
$(function() { 
    var maxIterations = 7000, 
     $times = $('#times'); 

    var iterator = new Iterator(function (next) { 
     var now = new Date(); 

     window.setTimeout(function() { 
      var ms = (new Date() - now); 

      $times.append($('<li></li>').text('Iteration ' + ($times.find('li').length + 1) + ': ' + ms + ' ms')); 

      maxIterations -= 1; 
      if (maxIterations > 0) { 
       next(); 
      } 
     }, 100); 
    }); 

    iterator.start(); 
}); 
</script> 

這導致了一個inter原因觀察:Chrome比Internet Explorer有更好的計時器。

Chrome的輸出樣本:

Iteration 5687: 101 ms 
Iteration 5688: 101 ms 
Iteration 5689: 101 ms 
Iteration 5690: 101 ms 
Iteration 5691: 101 ms 
Iteration 5692: 101 ms 
Iteration 5693: 101 ms 
Iteration 5694: 101 ms 
Iteration 5695: 100 ms 
Iteration 5696: 101 ms 
Iteration 5697: 101 ms 
Iteration 5698: 101 ms 
Iteration 5699: 102 ms 

現在的Internet Explorer:

•Iteration 5687: 92 ms 
•Iteration 5688: 93 ms 
•Iteration 5689: 108 ms 
•Iteration 5690: 93 ms 
•Iteration 5691: 109 ms 
•Iteration 5692: 92 ms 
•Iteration 5693: 93 ms 
•Iteration 5694: 109 ms 
•Iteration 5695: 93 ms 
•Iteration 5696: 92 ms 
•Iteration 5697: 109 ms 
•Iteration 5698: 93 ms 
•Iteration 5699: 108 ms 
+0

哇,這看起來真的像完美的解決方案我問題。謝謝 – 2015-02-11 01:44:53

+0

@southzrgw嘿沒問題。很高興它很有用。 – Paul 2015-02-11 22:47:15

0

我遇到這種類型的問題,當我想從外部數據庫複製記錄到sql lite db使用javascript。 一般for循環不會讓你作出這樣的等待Ajax請求調用到下一次迭代遞歸代碼,那麼我建議你的是:

  1. 使你的代碼爲全球儘可能把所有的對象以相同的方式
  2. 得到的對象將它們放到一個表
  3. 做一個函數,對象作爲參數的每一次表和 它 完成,將與下一個元素再次調用它自己的要求,直到達到表的末尾。

例如:

function recursive_calls(var elements[],var currentPosition){ 
    if(currentPosition<elements.length){ 
     $.ajax({ 
      url:some_api/elements[i].id, 
      method:'get', 
      success:function(res){ 
      //after some time ajax success function is fired 
      //do some stuff here 
      //call recursive_calls function again 
       currentPosition++; 
       recursive_calls(elements,currentPosition); 
      } 
     }); 
    } 
}