我的应用程序有大量$.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。
答案 0 :(得分:2)
现在是时候进行一些核心学习了。需要采取一些措施:
.done()
和.fail()
只是jQuery.ajax()
选项,没有所谓的过滤功能" jQuery 3+中的.then(successCallback, errorCallback)
(或.then()
/ .catch()
)。换句话说,从.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+)
});
});
<强> Fiddle 强>
现在尝试更换标记为&#34的行;传播行为&#34;并且&#34;捕捉行为&#34;并观察日志中的差异。
不要担心,如果你没有立即得到它。学习这些东西需要时间。如果您有选择,那么就开始使用jQuery 3+,其中jqxhr和其他Promise更接近javascript的原生Promise
而不是jQuery&lt; 3。