我在我们的应用程序的其他地方使用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
答案 0 :(得分:3)
由于jQuery的非标准承诺,你必须通过箍来将错误传递给Q-coerced promise。
事实上,jqXHR的错误签名是(jqXHR, textStatus, errorThrown)
,您通常希望传递第二个arg,textStatus
。
其次,两个promise实现在错误处理方面完全不同:
.then()
错误回调中返回一个新的,已解析的promise。无论返回什么,.fail()
都保证传播错误状态。未被捕获的throw
将终止事件线程。.catch()
,.fail()
或.then()
错误回调重新发生错误或抛出新错误,在这种情况下,承诺将继续沿错误路径行进。 因此,您需要:
.then(null, errHandler)
到jQuery.ajax()
来电以报告textStatus
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;
});
};