2015-10-20 45 views
4

我在jQuery中使用通常的鏈接延遲方法進行一系列連續的AJAX調用。第一次調用返回一個值列表,隨後的調用是使用返回的列表條目進行的。在第一次調用返回列表後,隨後的調用可以按任意順序完成,但必須一次完成一次。所以這是我使用的:繼續失敗的jQuery推遲鏈

$.when(callWebService()).then(
function (data) { 
    var looper = $.Deferred().resolve(), 
     myList = JSON.parse(data); 
    for (var i in myList) { 
     (function (i) { 
      looper = looper.then(function() { // Success 
       return callWebService(); 
      }, 
      function (jqXHR, textStatus, errorThrown) { // Failure 
       if (checkIfContinuable(errorThrown) == true) 
        continueChain(); 
       else 
        failWithTerribleError(); 
      }); 
     })(i); 
    } 
}); 

事實證明,後來的調用可能會失敗,但我仍然想要做其餘的調用。在我的上市,這就是創造性的僞代碼這一點是爲了做:

if (checkIfContinuable(errorThrown) == true) 
    continueChain(); 
else 
    failWithTerribleError(); 

如何在地球上我雖然實現continueChain?看起來,任何延期的失敗都會導致鏈條的其他部分也失敗。相反,我想記錄錯誤並繼續處理列表的其餘部分。

+0

'continueChain'和'failWithTerribleError'做了什麼? – Joseph

+0

請參閱http://stackoverflow.com/questions/27171161/handling-different-success-and-fail-states-for-multiple-ajax-call-using-deferred,http://stackoverflow.com/questions/28131082/ jquery-ajax-prevent-fail-in-a-deferred-sequential-loop – guest271314

+0

@CobusKruger嘗試使用'.always()' – guest271314

回答

5

隨着Promises/A+這是那麼容易,因爲

promise.then(…, function(err) { 
    if (checkIfContinuable(err)) 
     return valueToConinueWith; 
    else 
     throw new TerribleError(err); 
}) 

不幸的是,jQuery is still not Promises/A+ compliant,並轉發舊值(結果或錯誤) - 除非你返回從回調延遲一個jQuery。這個工程只是以同樣的方式爲rejecting from the success handler

jDeferred.then(…, function(err) { 
    if (checkIfContinuable(err)) 
     return $.Deferred().resolve(valueToConinueWith); 
    else 
     return $.Deferred().reject(new TerribleError(err)); 
}) 
+0

你知道是否有類似的解決方案使用'.fail()'方法?我根本不需要並行成功處理程序(您有'...'的地方),但似乎只有在使用2或3參數形式的'then'時,這個答案纔有效。我問這是一個單獨的問題[這裏](http://stackoverflow.com/questions/35614632/error-handling-and-recovery-with-jquery-deferred) – thedarklord47

1

從一個jQuery承諾鏈中的錯誤中恢復的比承諾/ A +實現,這自然趕在.catch的或。後來的錯誤處理程序錯誤的更多詳細。您必須拋出/重新拋出才能傳播錯誤狀態。

jQuery的工作原理是相反的。 .then的錯誤處理程序(.catch不存在)將自然傳播錯誤狀態。爲了模仿「捕捉」,你必須返回一個已解決的承諾,並且該鏈將沿着其成功的道路前進。

從您想要基於一系列異步調用的項目數組開始,使用Array.prototype.reduce()很方便。

function getWebServiceResults() { 
    return callWebService().then(function(data) { 
     var myList; 

     // This is genuine Javascript try/catch, in case JSON.parse() throws. 
     try { 
      myList = JSON.parse(data); 
     } 
     catch (error) { 
      return $.Deferred().reject(error).promise();//must return a promise because that's what the caller expects, whatever happens. 
     } 

     //Now use `myList.reduce()` to build a promise chain from the array `myList` and the items it contains. 
     var promise = myList.reduce(function(promise, item) { 
      return promise.then(function(arr) { 
       return callWebService(item).then(function(result) { 
        arr.push(result); 
        return arr; 
       }, function(jqXHR, textStatus, errorThrown) { 
        if(checkIfContinuable(errorThrown)) { 
         return $.when(arr); // return a resolved jQuery promise to put promise chain back on the success path. 
        } else { 
         return new Error(textStatus);//Although the error state will be naturally propagated, it's generally better to pass on a single js Error object rather than the three-part jqXHR, textStatus, errorThrown set. 
        } 
       }); 
      }); 
     }, $.when([])) // starter promise for the reduction, resolved with an empty array 

     // At this point, `promise` is a promise of an array of results. 

     return promise.then(null, failWithTerribleError); 
    }); 
} 

注:

  • 的整體功能包裝假定,function getWebServiceResults() {...}
  • callWebService()被認爲接受item - 即myList的每個元素的內容。
  • 要完成工作,checkIfContinuable()必須至少接受一個參數。假定接受errorThrown,但可能同樣接受jqXHR或textStatus。