2015-10-20 92 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。