JavaScript For循环中的异步调用

JavaScript Aysnchronous Call in For Loop

我想循环检查列表中的大约 3000 个项目。在每个步骤中,我都必须在页面上进行异步 httprequest。使它成为一个递归函数 ist throwing InternalError: too much recursion 到目前为止,这是我的代码:

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

如何更改我的代码以避免递归函数并且一次只处理一个请求?

当我想使用 javascript 将记录从外部数据库复制到 sql 精简版数据库时,我遇到过此类问题。 通常 for 循环不会让你编写递归代码等待 ajax 请求调用进入下一次迭代,那么我推荐你的是:

  1. 使您的代码尽可能全局化,以便以相同的方式处理所有对象
  2. 获取对象将它们放入 table
  3. 创建一个函数,每次以对象的table为参数 它 完成请求后,它将使用下一个元素再次调用它自己,直到到达 table.
  4. 的末尾

示例:

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

只是为了添加另一个解决方案,我认为这是一个有趣的问题,所以这是我根据您的原始解决方案编写的内容:

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>

这导致了一个有趣的观察: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