【问题标题】:Get more information from a failed JQuery jqXHR request从失败的 JQuery jqXHR 请求中获取更多信息
【发布时间】:2014-10-24 05:47:19
【问题描述】:

我正在使用 JQuery 的 $.when$.get 来获取一些数据并对其进行处理。当获取它或使用它做某事发生错误时,我想处理该错误,并根据我正在获取的数据/在哪个路径获取它以不同方式处理它。

很遗憾,传递给$.when().fail(...) 的信息很少,并且不包括该信息。我怎样才能以一种非 hacky[1] 的方式从可延迟的对象中冒泡这些信息?

$.when(get(path1), get(path2)
  .done(function(parsed1, parsed2) {
    // do something with this date
  }).fail(function(jqXHR, statusTxt, errTxt) {
    // do something depending on which path failed...
  });

function get(path) {
  var parser = U.parser();
  return $.get('/getter' + path)
    .then(function(data) {
      return parser(data);
    });
}

[1]:当然,我可以关闭路径和一些我想要处理失败的全局对象,并在 $.get 返回的 Deferred 上的 .fail() 中处理它。我也可以传递一个没有失败但以某种方式包装失败的 Deferred ,但这也感觉很hacky。

【问题讨论】:

  • vcfPath 是唯一的“路径”吗?
  • 那么您将在statusTxterrText 中获得详细信息,如果客户端或请求存在问题,但如果存在服务器错误,那么显然该信息不能通过这些参数很容易得到。
  • @guest271314 是的,它是(编辑为path)。
  • @Isaac 可以将path 附加到beforeSend 处的jqxhr 对象,然后在.fail() 处解析jqxhr 以获取特定路径;为特定路径做事。
  • @Isaac 见帖子。谢谢

标签: jquery ajax jqxhr


【解决方案1】:

由于 jqXHR 对象是传递回$.when() 的东西之一,因此您似乎可以将与您的请求相关的东西放在那里。例如,如果路径是您想要的,您可以这样做:

function get(path) {
  var parser = U.parser();
  var p = $.get('/getter' + vcfPath)
    .then(function(data) {
      return parser(data);
    });
  p.myPath = path;
  return p;
}

然后,在您的 $.when() 处理程序中,您将拥有可以从中提取参数的 jqXHR 对象。

注意,$.when() 会在任何单个请求被拒绝时立即拒绝。如果您确实希望所有请求继续并且您想知道所有请求何时都已完成(无论是已解决还是被拒绝),您不能为此使用$.when()。 jQuery 本身并不提供该功能。您可以自己构建它,也可以使用提供该功能的外部 Promise 库(我使用具有 Promise.settle() 的 Bluebird。

这是一个工作示例:

var data = {
    json: JSON.stringify({
        text: 'some text',
        array: [1, 2, 'three'],
    }),
    delay: 1
}


function runAjax(data, value) {
    var p = $.ajax({
        url:"/echo/json/",
        data:data,
        type:"POST",
    });
    // put something on the jqXHR object for retrieval later
    p.myData = value;
    return p;    
}

function runAjaxFail(data, value) {
    var p = $.ajax({
        url:"/echo/junk/",
        data:data,
        type:"POST",
    });
    // put something on the jqXHR object for retrieval later
    p.myData = value;
    return p;    
}

$.when(runAjax(data, "Hello"), runAjax(data, "GoodBye"), runAjaxFail(data, "My Fail Message")).then(function(r1, r2) {
    // for each arg [0] is data, [1] is status, [2] is jqXHR object
    log(r1[2].myData);   // logs "Hello"
    log(r2[2].myData);   // logs "GoodBye"
}, function(jqXHR, textStatus, errorThrown) {
    // fail handler
    log("fail: " + jqXHR.myData);
});

工作演示:http://jsfiddle.net/jfriend00/g8z353cz/


这是在 Promise 世界中完全支持的另一种方法。这接管了 ajax 承诺的解析,以便您可以将任何您想要的数据放入其中。在这个特定的实现中,我选择始终解析并仅使用解析值中的数据来告诉您哪些 ajax 调用成功或失败,但如果您愿意,您也可以使用带有值的拒绝。这保证会一直传播回来:

function get(path) {
    var parser = U.parser();
    var d = $.Deferred();
    $.get('/getter' + path)
        .then(function(data) {
            d.resolve(parser(data));
        }, function(jqXHR) {
            // error handler
            d.resolve({path: path, jqXHR: jqXHR});
        });
    return d.promise();
}

而且,你可以在这里看到这种实现:http://jsfiddle.net/jfriend00/c0u40gqh/

【讨论】:

  • 嗯,这似乎对我不起作用:这样做不会向我在失败回调时进入的 jqXHR 对象添加myPath 属性。
  • @Isaac - jQuery 如何将参数传递给$.when() 有点令人困惑(如果有一个承诺与多个承诺,它的工作方式会有所不同)。无论如何,这是一个可行的示例,说明您如何按照我的建议进行操作。
  • 这对.fail() 不起作用(或者如果它起作用,我不知道如何),在这种情况下我需要额外的信息。
  • @Isaac - 您只需为失败处理程序获取正确的参数,它就可以工作。请参阅修改后的代码,其中我向您展示了参数如何为失败处理程序工作,我什至在工作演示中展示了失败的 ajax 调用。
  • 啊,迷人;这适用于$.ajax(…),但不适用于$.get(…)!有趣/离奇;知道为什么吗?
【解决方案2】:

试试

注意,在第一个 error 处停止,但可以为此实施解决方法。下面主要针对可能的自定义错误模式

var data = {
    "path1" : function() { return {"path1" : [1,2,3]} },
    "path2" : function() { return {"path2" : [7, 8, 9] }},
    "path1Error" : function() {
        console.log("path1 error")
     },
     "path2Error" : function() {
        console.log("path2 error")
     }
};

    $.ajaxSetup({
      beforeSend: function(jqXHR, settings) {
        var path = JSON.parse(
            decodeURIComponent(settings.data.split("=")[1])
        );
          jqXHR.path = (path + "Error") in data 
          ? data[path + "Error"] 
          : path + "Error";
      }
    });

$.when(get("path1"), get("path2"))
  .done(function(parsed1, parsed2) {
      //console.log(parsed1, parsed2)
    // do something with this date
  })
  .fail(function(jqXHR, statusTxt, errTxt) {      
      jqXHR.path()
    // do something depending on which path failed...
  });

function get(path) {
    var parser = function (p) { return data[p]()};
    // `error`
    return $.post("/echo/jsons/", {json:JSON.stringify([path]) })
    .then(function(data) {
      return parser(data[0]);
    });
}

jsfiddle http://jsfiddle.net/guest271314/o3Lk73wg/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 2013-04-26
    • 2012-04-19
    • 2015-02-21
    相关资源
    最近更新 更多