使用Q处理jQuery AJAX的错误处理

时间:2015-03-13 03:52:55

标签: jquery ajax error-handling promise q

我在我们的应用程序的其他地方使用jQuery但是Q,所以要确保Promise实现是一致的。

我用Q包装了jQuery AJAX调用,如下所示:

Q($.ajax(url, {
  type: 'get'
}));

它对于成功的反应都很好。现在我想添加错误处理,我想要进行全局错误处理(因为我们的服务器有一致的错误响应),制作如下的API:

var xhr = function (url) {
    return Q($.ajax(url, {
      type: 'get'
    }))
    .then(function (data) {
      return data;
    }, function (res) {
      //global error handling
    });
};

我希望像这样使用它:

xhr('...').then(function () { console.log('success'); });

问题是当全局错误处理程序运行"成功"调用xhr方法的使用者的方法。

你会如何防止这种情况?

这里可以看到一个可运行的样本 - http://jsbin.com/gudifu/3/edit

2 个答案:

答案 0 :(得分:3)

由于jQuery的非标准承诺,你必须通过箍来将错误传递给Q-coerced promise。

事实上,jqXHR的错误签名是(jqXHR, textStatus, errorThrown),您通常希望传递第二个arg,textStatus

其次,两个promise实现在错误处理方面完全不同:

  • jQuery :传播错误状态,除非从.then()错误回调中返回一个新的,已解析的promise。无论返回什么,.fail()都保证传播错误状态。未被捕获的throw将终止事件线程。
  • :标记错误"已处理" (即将其发送到成功路径)除非.catch().fail().then()错误回调重新发生错误或抛出新错误,在这种情况下,承诺将继续沿错误路径行进。

因此,您需要:

  • .then(null, errHandler)jQuery.ajax()来电以报告textStatus
  • 根据jQuery错误从Q中抛出错误
var xhr = function (url) {
    return Q($.ajax(url, {
      type: 'get'
    }).then(null, function(jqXHR, textStatus, errorThrown) {
        return textStatus;
    })).then(function (data) {
        return data;
    }, function (textStatus) {
      //global error handling
      throw new Error(textStatus);
    });
};

你也可以从jQuery中抛出一个正确的错误,然后简单地从Q中重新抛出它。

var xhr = function (url) {
    return Q($.ajax(url, {
      type: 'get'
    }).then(null, function(jqXHR, textStatus, errorThrown) {
        return new Error(textStatus);
    })).then(function (data) {
        return data;
    }, function (err) {
      //global error handling
      throw err;
    });
};

两种解决方案的净效果非常接近。如果记录错误,我认为我会说他们会显示不同的错误行号 - 前者源自Q而后者源于jQuery。

答案 1 :(得分:1)

您的问题是全局错误处理程序处理错误。作为承诺链,无论错误处理程序返回什么,您的xhr(…)承诺都将履行。它就像catch,当处理了异常时,恢复正常执行。

因此,您需要从处理程序中重新抛出异常,以便生成的promise也会被拒绝:

var xhr = function (url) {
    return Q($.ajax(url, {
        type: 'get'
    }))
    .then(null, function (res) {
        //global error handling
        throw res;
    });
};