1.5版本后的jquery使用$.ajax()返回的是deferred对象
大家都知道deferred对象是jquery给出的回调函数的解决方案
ajax请求可以写成以下形式
$.ajax('target.html')
.done(function(){})
.fail(function(){});
非常简单明了
但现在情况是返回数据中有一字段规定请求失败与否(不是通信问题的错误)
一般jquery的ajax的使用如下(当然是我比较晚知道这个deferred这个对象,可能大家老早就不这样写了)
$.ajax({
url: target.html,
success: function(){},
error: function(){}
});
改写如下
var IO = {};
IO.prototype.ajaxGet = function(url, params, cb, error) {
$.ajax({
url: url,
type: 'get',
data: params,
success: function(data) {
data = $.parseJSON(data);
if(data.state != 10000) {
error && error(data);
return false;
}
cb && cb(data);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
//这里是出现请求失败等问题的处理
}
});
}
因为与后台约定好当返回state字段值不为10000则算是错误情况
需要到error函数中执行
但是在success与error中要如何获取deferred对象来进行改写
使之可以像本题最上面的写法使用
如
IO.ajaxGet('target.html', data)
.done(function(data){})
.fail(function(data){});
不,你不能在 success/error 回调中获取 deferred 对象的结果(或者说你已经在它的结果中了),这是因为 deferred 对象包含的是“未来”的结果——在你获取 deferred 对象的时候,它所代表的异步请求还没发生。并且正因为如此,我们才能利用 deferred 对象来去定义未来可能发生的事情,要么 success(resolved),要么 error(rejected)。所以在 success/error 回调中获取 deferred 对象是没有意义的,就好像“在未来中获取代表未来的那个过去对象”。
那么要怎么做?
从大的层面上来讲,API 的设计不够完整。你们可以自定义错误代码/错误信息,但更重要的是如果发生了错误,那就应该同时修改 HTTP 状态码。我记得 jQuery 的 Ajax 请求会拦截非 2xx 的 HTTP 响应,然后走 error 回调,因此如果你们这样做了,那么属于错误的部分就应该在 deferred.fail() 里面去处理。这才是正途。
当然现实总是很傻缺,错误也经常以 200 的形式返回给客户端,所以我们不得不在 success 回调中处理异常。那么使用 deferred 的时候怎么做呢?
deferred 这种模式和 Promise 很像,它也是一个 thenable 对象,它的 then 方法可以让你串联多个函数并依次执行。所以你可以写一个通用的过滤函数来处理返回错误对象的情况,然后 reject 整个 deferred 对象。由于我很久没用 jQuery 了,以下示例代码仅凭印象写下,你就当是伪代码,看个意思就好:
var deferred = $.ajax({
url: url,
type: 'get',
data: params,
...
});
function processError(response) {
if (!(response.state == 10000)) {
// reject deferred 对象,并将状态码传给 .fail() 的回调
return deferred.reject(response.state);
}
deferred.resolve(response); // 这一句可能不需要,细节记不清了
}
deferred
.then(processError) // 调用上面的函数,过滤异步请求的结果
.done(processYourBussiness) // 处理正常逻辑
.fail(errorHandler); // 处理异常逻辑
你可能会想不要 errorHandler 转而直接在 processError 里处理异常,但是记住我们之所以这么做,其实就是在“模拟”正确的模式,用 processError 来代替本来应该发生的 HTTP Status 不等于 2xx 的情形。这样一来,无论 API 那里是否处理正确,客户端总是走在正确的轨道上,将来若是 API 更改,处理了正确的状态码,那就只需要去掉 processError 编好,它相当于一个中间件。
若有可能,还是用 Promise 吧,jQuery 的 deferred 实现是有缺陷的。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。