我的应用程序有很多$.ajax调用,它们大多具有.done和.fail函数。
我希望围绕Ajax调用编写一个包装器,这样如果一个函数没有.fail函数,或者如果.fail函数不处理给定的错误(例如,它只处理404,但我得到了一个403),那么我希望包装器可以作为后盾处理它。
以下是我所写的:
function DoAjax(fn, errorText) {
var deferred = $.Deferred();
var result = fn();
if (result === undefined)
throw 'Function passed into DoAjax has not returned a promise.';
result.always(function () {
deferred.resolve(result);
});
result.fail(function () {
alert('fail');
deferred.fail();
});
return deferred.promise();
}它主要按照我的意愿工作,但失败将执行两次--一次在方法DoAjax中,另一次在Ajax调用的站点上。
我这样执行DoAjax:
DoAjax(function () {
var ajaxCall = $.ajax({
method: "GET",
url: baseUrl + "api/test"
});
ajaxCall.fail(function() { alert('failed the call'); });
return ajaxCall;
});我相信我可能可以通过手动创建一个$.deferred,然后围绕它执行$.ajax调用来实现这一点,但是不希望在它周围有另一个包装器。
我使用的是jQuery 2.2。
发布于 2018-01-14 23:41:28
是时候好好学习了。有几件事需要考虑进去:
.done()和.fail()只是没有.then(successCallback, errorCallback) (或jQuery 3+中的.then()/.catch() )所谓的“过滤能力”的jQuery.ajax()选项。换句话说,无论从.done()和.fail()回调中返回什么,都不会对jqxhr承诺链产生下游影响。fn()返回jqxhr,而不是结果。因此,正如所写的那样,if(result === undefined)测试将始终返回false。jqxhr最终交付的结果不能以这种方式进行测试。jQuery.when(...)中,例如$.when(fn())。jQuery.when(...)返回的承诺中链接。不需要显式的$.Deferred()。试试这个:
var baseUrl = '/';
function DoAjax(fn) {
return $.when(fn()) // no need to test for fn() not returning a promise. `$.when(fn())` forces any non-Promise to Promise.
.then(function(response) {
console.log('success!', response);
}).then(null, function(err) {
console.error('B', err); // (LOG_2)
});
}
DoAjax(function () {
return $.ajax({
method: "GET",
url: baseUrl + "api/test"
}).then(null, function(jqxhr, textStatus) {
var err = new Error('Whoops! ' + jqxhr.status + ': ' + textStatus);
console.error('A', err);
// "throw behaviour"
return err; // propagate the error (jQuery <3) or `throw err;` (jQuery 3+)
// "catch behaviour"
// return $.when('default response'); // "2" mutate failure into success (jQuery <3) or `return 'default response';` (jQuery 3+)
});
});现在,尝试交换标记为“繁殖行为”和“捕获行为”的行,并观察日志中的差异。
如果你不马上拿到的话就别担心。学习这些东西需要时间。
如果您有选择,那么使用jQuery 3+,其中jqxhr和其他承诺更接近javascript的原生Promise,而不是jQuery <3。
https://stackoverflow.com/questions/48253972
复制相似问题