2014-08-28 79 views
1

我需要遞歸異步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

回答

1

我試圖使用$ .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

0

爲簡單起見,你可以只運行在你的.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

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

目前未經測試,但它至少給你的想法。基本上,只有解決了所有後續調用後才能解決延期問題。

+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

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/

+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