1、需求背景
很多时候,我们使用jquery.ajax的方式向后台发送请求,型如
$.ajax({
type: "post",
url: "/User/Edit",
data: { data: JSON.stringify(postdata) },
success: function (data, status) {
if (status == "success") {
toastr.success('提交数据成功');
$("#tb_aaa").bootstrapTable('refresh');
}
},
error: function (e) {
},
complete: function () {
}
});
复制代码
这种代码太常见了,这个时候我们有这样一个需求:在自己调用ajax请求的时候,我们不想每次都写error:function(e){}这种代码,但是我们又想让它每次都将ajax的错误信息输出到浏览器让用户能够看到。怎么办呢?或者我们需要使用Cros时,Header里面需要带上Token值,而不想每次都去加上beforeSend: function (request) {request.setRequestHeader(“token”, token);},
2、实现原理
要想实现以上效果其实并不难,我们可以将
.
a
j
a
x
(
)
封
装
一
层
,
在
封
装
的
公
共
方
法
里
面
定
义
e
r
r
o
r
对
应
的
事
件
即
可
。
确
实
,
这
样
能
达
到
我
们
的
要
求
,
但
是
并
不
完
美
,
原
因
很
简
单
:
1
)
在
j
q
u
e
r
y
的
基
础
上
面
再
封
装
一
层
,
效
率
不
够
高
;
2
)
需
要
改
变
调
用
者
的
习
惯
,
每
次
调
用
a
j
a
x
的
时
候
需
要
按
照
我
们
定
义
的
方
法
的
规
则
来
写
,
而
不
能
直
接
用
原
生
的
.ajax({})封装一层,在封装的公共方法里面定义error对应的事件即可。确实,这样能达到我们的要求,但是并不完美,原因很简单: 1)在jquery的基础上面再封装一层,效率不够高; 2)需要改变调用者的习惯,每次调用ajax的时候需要按照我们定义的方法的规则来写,而不能直接用原生的
.ajax()封装一层,在封装的公共方法里面定义error对应的事件即可。确实,这样能达到我们的要求,但是并不完美,原因很简单:1)在jquery的基础上面再封装一层,效率不够高;2)需要改变调用者的习惯,每次调用ajax的时候需要按照我们定义的方法的规则来写,而不能直接用原生的.ajax({})这种写法,这是我们不太想看到。
既然如此,那我们如何做到既不封装控件,又能达到以上要求呢?答案就是通过我们的$.extend去扩展原生的jquery.ajax。
其实实现起来也并不难,通过以下一段代码就能达到我们的要求。
复制代码
(function ($) {
//1.得到$.ajax的对象
var _ajax = $.ajax;
$.ajax = function (options) {
//2.每次调用发送ajax请求的时候定义默认的error处理方法
var fn = {
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error(XMLHttpRequest.responseText, '错误消息', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' });
},
success: function (data, textStatus) { },
beforeSend: function (XHR) { },
complete: function (XHR, TS) { }
}
//3.如果在调用的时候写了error的处理方法,就不用默认的
if (options.error) {
fn.error = options.error;
}
if (options.success) {
fn.success = options.success;
}
if (options.beforeSend) {
fn.beforeSend = options.beforeSend;
}
if (options.complete) {
fn.complete = options.complete;
}
//4.扩展原生的$.ajax方法,返回最新的参数
var _options = $.extend(options, {
error: function (XMLHttpRequest, textStatus, errorThrown) {
fn.error(XMLHttpRequest, textStatus, errorThrown);
},
success: function (data, textStatus) {
fn.success(data, textStatus);
},
beforeSend: function (XHR) {
fn.beforeSend(XHR);
},
complete: function (XHR, TS) {
fn.complete(XHR, TS);
}
});
//5.将最新的参数传回ajax对象
_ajax(_options);
};
})(jQuery);
生产环境示例:
将以下代码保存为js文件,在需要异步调用的页面调用
这样,每次请求就在Header里面自动带上了token值,该值由Cookies里面提供,在Cros请求中使用就非常方便了!
(function ($) {
//1.得到$.ajax的对象
var _ajax = $.ajax;
var _token = getCookie("token");
$.ajax = function (options) {
//2.每次调用发送ajax请求的时候定义默认的error处理方法
var fn = {
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error(XMLHttpRequest.responseText, '错误消息', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' });
},
success: function (data, textStatus) { },
beforeSend: function (XHR) { },
complete: function (XHR, TS) { }
}
//3.扩展原生的$.ajax方法,返回最新的参数
var _options = $.extend({}, {
error: function (XMLHttpRequest, textStatus, errorThrown) {
fn.error(XMLHttpRequest, textStatus, errorThrown);
},
success: function (data, textStatus) {
fn.success(data, textStatus);
},
beforeSend: function (XHR) {
XHR.setRequestHeader('token', _token);
fn.beforeSend(XHR);
},
complete: function (XHR, TS) {
fn.complete(XHR, TS);
}
}, options);
//4.将最新的参数传回ajax对象
_ajax(_options);
};
function getCookie(name) {
var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
if (arr != null) return unescape(arr[2]); return null;
};
})(jQuery);