在递归异步ajax调用之后执行一个函数

时间:2014-08-28 14:15:40

标签: javascript jquery ajax recursion jquery-deferred

我需要在递归异步ajax调用之后执行一个函数。 我有:

var tree = [1, 2 ,3, 4];

recursion(0);

function recursion(i) {
    $.ajax('http://example.com/' + tree[i])
        .done(function (data) {
        // data is array
        ++i;
        if (tree[i] !==undefined) {
            $.each(data, function () {
                recursion(i);
            });
        }
    });
}

我希望完成后的所有通话

recursion(0).done(function () {alert('All calls are done!')});

我知道,我应该使用$ .Deferred of JQuery,但是ajax调用也会返回promise。 我试图使用$ .Deferred但我在这个地方遇到了循环问题:

     $.each(data, function () {
         recursion(i);
     });

请帮助我。

4 个答案:

答案 0 :(得分:1)

你需要做这样的事情:

function recursion(i) {

    return $.ajax('http://example.com/' + tree[i])
        .then(function (data) {
            // data is array
            ++i;
            if (tree[i] !==undefined) {

                // get an array of promises
                var promises = $.map(data, function () {
                    return recursion(i);
                });

                // return the `when` promise from the `then` handler 
                // so the outer promise is resolved when the `when` promise is
                return $.when.apply($, promises);
            } else {
                // no subsequent calls, resolve the deferred
            }
        });
}

目前尚未经过测试,但它至少可以为您提供这个想法。基本上,只有在解决了所有后续调用后才解决延迟问题。

答案 1 :(得分:1)

  

我试图使用$ .Deferred

好!

  

但是我在这个地方遇到了循环问题:$.each(data, recursion)

每个recursion(i)调用都会返回一个承诺,所以当我们将它们踢掉时,我们会留下一系列承诺。现在,我们可以使用$.whenwait for all of them,并取消对所有结果的承诺。

现在,我们使用then在ajax调用之后链接这个循环执行,这样我们就可以为这个递归步骤的最终结果返回一个promise。

function recursion(i, x) {
    return $.ajax('http://example.com/' + tree[i] + x).then(function (data) {
        if (++i < tree.length)
            // get an array of promises and compose all of them
            return $.when.apply($, $.map(data, function(d) {
                return recursion(i, d);
            }));
        else // at the innermost level
            return data; // get the actual results
    }); // and return a promise for that
}

答案 2 :(得分:0)

为简单起见,您可以在.done中运行一个函数来检查i的值,如果它等于树的长度(减去1),则运行您的函数。

很抱歉,这不包括异步性质......而是...创建一个跟踪已完成数量的变量,并与数组中的数字进行比较。如果相等,请运行您的功能。

答案 3 :(得分:0)

编辑,jquery deferredpromise实际上并不需要达到要求。请参阅下面的Bergi评论和链接。

尝试(此模式; 不带 jquery.deferredpromise

   (function recursion() {
        var tree = [1, 2 ,3, 4]
        , results = []
        , dfd = function(res) {
            alert('All calls are done!');
            console.log(res)
        };

    $.each(tree, function(k, v) {
        $.ajax("http://example.com/" + v)
        .done(function (data, status, jqxhr) {
        // data is array
          results.push([data, status, jqxhr.state()]);
            if (results.length === tree.length) {
              dfd(results);          
            }
        });

    });

    }());

jsfiddle http://jsfiddle.net/guest271314/nvs0jb6m/