为jQuery延迟对象提供默认的“fail”方法

我正在使用jQuery编写Javascript API客户端。 我的顶级请求方法如下所示:

function request(method, uri, params, proxies) { var deferred = $.Deferred(); $.ajax({ data: method == 'GET' ? params : JSON.stringify(params), contentType: 'application/json', dataType: 'json', url: api.root + uri, type: method, xhrFields: { withCredentials: true } }).done(function(body) { deferred.resolveWith(this, [body.data]); }).fail(function(xhr) { deferred.rejectWith(this, [xhr]); }); return deferred.promise(); }, 

如何为返回的延迟提供默认的fail处理程序? 也就是说,如果deferred没有附加到其fail条件的其他处理程序,则调用默认处理程序。

我想这样做是为了在我的应用程序中进行全局exception处理,除了具有特定处理的部分(并且将在延迟上定义自己的fail处理程序)。

因此,截至2016年,在API中使用jQuery ajax的最简洁方法是返回一个承诺。 但是,您无法确定调用者是否已将error handling程序附加到promise。

所以,我建议你只是在你的函数中添加一个新的参数,告诉函数不应用默认的error handling,因为调用者将负责error handling。 并且,我建议你通过使用现有的承诺$.ajax()已经返回而不是创建自己的延迟来避免承诺反模式:

 function request(method, uri, params, proxies, skipDefaultErrorHandling){ // default error handling will be used if nothing is passed // for skipDefaultErrorHandling var p = $.ajax({ data: method=='GET'?params:JSON.stringify(params), contentType: 'application/json', dataType: 'json', url: api.root + uri, type: method, xhrFields: { withCredentials: true } }); if (!skipDefaultErrorHandling) { // apply default error handling p = p.then(null, function(jqXHR, textStatus, errorThrown) { // put here whatever you want the default error handling to be // then return the rejection with the various error parameters available return $.Deferred().reject([jqXHR, textStatus, errorThrown]); }); } return p; }; 

然后,调用者只决定是否应用自己的error handling:

 request(...).then(function(data) { // success code here }); 

或者,您可以使用传入的非承诺failHandler回调,并且您的默认error handling会查看是否传入了failHandler 。 这是承诺和回调的混合,并不是我通常会选择设计的东西,但是由于你的问题要求承诺不支持的东西,这是实现这一点:

 function request(method, uri, params, proxies, failHandler){ // default error handling will be used if nothing is passed // for skipDefaultErrorHandling var p = $.ajax({ data: method=='GET'?params:JSON.stringify(params), contentType: 'application/json', dataType: 'json', url: api.root + uri, type: method, xhrFields: { withCredentials: true } }); // apply default error handling p = p.then(null, function(jqXHR, textStatus, errorThrown) { if (failHandler) { // call passed in error handling failHandler.apply(this, arguments); } else { // do your default error handling here } // then keep the promise rejected so the caller doesn't think it // succeeded when it actually failed return $.Deferred().reject([jqXHR, textStatus, errorThrown]); }); return p; };