执行的函数的递归异步Ajax调用

问题描述:

我需要递归异步Ajax调用后执行功能之后。 我:执行的函数的递归异步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 $的jQuery,但AJAX调用返回的承诺太。 我试图使用$ .Deferred但我在这个地方遇到了问题循环:

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

请帮助我。

+0

你的'recursion()'甚至不返回一个承诺。 – Bergi 2014-08-28 14:22:44

+0

看看[这个问题](http://stackoverflow.com/q/21762982/1048572)虽然和[这里](http:// stackoverflow。com/q/5627284/1048572)关于如何等待多个'recurse()'承诺 – Bergi 2014-08-28 14:25:42

+2

为什么当递归调用实际上不使用'data'时,为什么递归调用循环的'data'呢? ?它是否需要递归?您可能想发布您的实际代码。 – Bergi 2014-08-28 14:27:36

我试图使用$ .Deferred

好!

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

每个recursion(i)调用返回一个承诺,所以当我们踢他们离我们只剩下诺言的集合。现在,我们可以使用$.whenwait for all of them,并取回所有结果的承诺。

现在,我们使用then在ajax调用之后链接这个循环执行,以便我们可以返回此递归步骤最终结果的承诺。

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

你的答案陷入循环:(,冻结浏览器,当在'console',此页面尝试;没有返回结果在jsfiddle http://jsfiddle.net/guest271314/x8a8brak /?如果可能,可以在上面创建一个jsfiddle,以展示预期的结果?fwiw,为什么不简单地撰写和发布_own_答案而不是检查其他用户的努力_before_发布自己的答案?或者两者都有?如果您的方法/答案是真正最有效的答案,答案会说明问题,不是吗?可能有更多的方式,或“模式”,以达到相同的结果? – guest271314 2014-08-28 17:05:49

+2

我认为你有一个错误1你的'if(++ i ...'当'++ i'等于'tree.length'时,那么'tree [i]'在调用'recursion'时将是未定义的。你也定义了一个参数'x',但从来没有通过它。这是否意味着无论从循环中的“数据”中提取哪些信息? – 2014-08-28 17:44:45

+0

@ guest271314对于它的价值,我非常感谢Bergi对我的回答的评论,并因此改进了我对未来承诺的使用。我认为我在解决他的评论时迟缓导致他发布自己的答案。我自己也经常做同样的事情。如果答案类似于我会回答的问题,但是会漏掉几个关键点,我会将它们指出来,让答案者更新他的答案,而不是发布类似的答案。如果回答者不在(或者不愿意)更新,我会发布我自己的。 – 2014-08-28 17:51:49

为简单起见,你可以只运行在你的.done一个函数,检查i的值,如果它等于树的长度(减1),然后运行你的函数。

对不起,这不包括异步性...,而不是...创建跟踪的完成数的变量,并比较数组中的号码。当相等时,运行你的功能。

+0

虽然这并没有使用承诺的力量。 – Bergi 2014-08-28 14:26:18

+0

只是一个简单的方法来完成工作。对不起,我还没有使用承诺。 – 2014-08-28 14:26:50

+1

@Shane Stebner,是的,但是在循环中存在问题,在最后一步树中[3],当我检查“i”时,这个条件将会像数据数组中的元素那样执行多少 – BottieYOYO 2014-08-28 14:42:26

你需要做这样的事情:

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

目前未经测试,但它至少给你的想法。基本上,只有解决了所有后续调用后才能解决延期问题。

+0

请勿使用[deferred antipattern](https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#wiki-the-deferred-anti-pattern)!你甚至知道['$ .when'](http://api.jquery.com/jQuery.when/)! – Bergi 2014-08-28 15:43:28

+0

@Bergi我觉得我可能在这种情况下失去了一些愚蠢的东西,但是你打电话给'什么时候'?在函数返回并且ajax调用解析不充分时,延迟列表不存在,因为这太快了。 – 2014-08-28 15:49:44

+0

但是ajax承诺确实存在,你只需要[链接](http://api.jquery.com/deferred.then/)你的递归调用,这些调用被'$ .when'捆绑在一起。可能我的评论是误导性的,你使用'.when'是正确的,使用'def'和'ajax()。done(...)'不是。 – Bergi 2014-08-28 16:01:15

编辑,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/

+0

为什么你从IIFE返回字符串“pending”? – Bergi 2014-08-28 15:41:05

+0

请勿使用[deferred antipattern](https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#wiki-the-deferred-anti-pattern)!已经有[一个功能来做这个](http://api.jquery.com/jQuery.when/)。 – Bergi 2014-08-28 15:41:48

+0

在完成所有任务之前,'pending'是'deferred.state()'。最好是完全从这个延期退出?将重新撰写并发布_without_延迟。谢谢 – guest271314 2014-08-28 15:45:26