【问题标题】:Provide a default 'fail' method for a jQuery deferred object为 jQuery 延迟对象提供默认的“失败”方法
【发布时间】:2016-04-06 23:10:33
【问题描述】:

我正在使用 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 条件的其他处理程序,则调用默认处理程序。

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

【问题讨论】:

  • 延迟对象不是这样工作的。相反,有一个全局错误处理程序,然后禁用该 ajax 请求的全局事件。
  • 这里不要使用$.Deferred接口。只需在 $.ajax() 返回的承诺上调用 then 方法(或旧 jQuery 版本中的 pipe)!
  • 有一个全局的ajaxError event,你可以使用$.ajaxSetup作为默认选项。
  • ajaxError 不适合我,因为它会触发所有请求,无论是否有特殊处理。我知道这现在是标准的延迟行为,但有没有一种简单的方法可以实现同样的效果?
  • 您想要一个默认的失败处理程序或特定的失败处理程序。没有半途而废!

标签: javascript jquery jquery-deferred


【解决方案1】:

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

所以,我的建议是,您只需向函数添加一个新参数,告诉函数不要应用默认错误处理,因为调用者将负责错误处理。而且,我建议您通过使用现有的 promise $.ajax() 已经返回而不是创建自己的 deferred 来避免 promise 反模式:

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

然后,调用者只需决定是否应用自己的错误处理:

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

或者,您可以使用传入的非承诺 failHandler 回调,并且您的默认错误处理会查看是否传入了 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;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    相关资源
    最近更新 更多