之前寫過一篇 先定一個小目標,自己封裝個ajax,是基於原生js的,也就是jquery中ajax的簡化版本實現的思路。眾所周知,jquery的ajax是項目中最常用的請求后台的方式,也算是封裝的很完美的api了,然而漸漸的我們會發現,其實還可以根據實際項目需要更優雅的進行一層封裝,先看調用方式:

熟悉EasyUI的猿們可能會覺得這種方式有點熟悉,沒錯,我就是看easyUI得到的啟發,也顯然這樣的方式更利於前端做判斷,邏輯更清晰明了。那么代碼后面是怎樣封裝的呢,我這里貼出核心的代碼以及思路。
思路
將后台返回的不同業務狀態碼以函數回調的形式代替,減少if的多層級判斷。同時將通用的錯誤狀態碼邏輯(如這里的900狀態是通用異常)、通用的請求參數(如client客戶端來源,是否需要token證書)、請求前置觸發操作(如加載中動畫)等等進行統一處理,既減少的代碼量,同時又更利於維護。
封裝的js代碼
var LI = {
//發送get請求
GET: function(options){
this.ajax(options,'get');
},
//發送post請求
POST: function(options){
this.ajax(options,'post');
},
ajax: function(options,type){
var opts = {
isCommonBefore: true, //默認是通用的加載中動畫
client: 1, //TODO這里應該根據內核判斷
isCors: false,//默認不跨域
isLogin: false
}
$.extend(true, options, opts || {});
//跨域,將請求地址 和 請求參數 都作為參數傳遞調用后台固定的跨域接口
if (opts.isCors) {
opts.data = {
url: opts.url,//真實的url
params: JSON.stringify(opts.data), //請求參數
}
opts.url = URL.CORS;
}
//添加默認的參數
opts.data.client = opts.client;
//需要登錄認證的請求
if(opts.isLogin){
opts.data.token = LI.getToken()
}
$.ajax({
url: opts.url,
data: opts.data,
type: type,
async: opts.async,
beforeSend: function() {
opts.isCommonBefore ? LI.loadingShow() : (opts.beforeSend && opts.beforeSend())
},
success: function(json) {
if(json){
console.log(opts.baseUrl || opts.url,' ajax is successful',json);
opts.success && opts.success(json);
if(opts[json.status]){//區分不同的狀態碼回調函數
console.log(opts.baseUrl || opts.url,'ajax status is', json.status, '並已回調'+ json.status +'方法');
eval(opts[json.status])(json);
}
}else{
console.error(opts.baseUrl || opts.url,'ajax 數據返回格式異常');
LI.ajaxError();
}
},
error: function(){
console.error(opts.baseUrl || opts.url,' ajax is error');
opts.error != undefined ? opts.error() : LI.commonError();
},
complete: function(XMLHttpRequest, textStatus) {
console.log(opts.baseUrl || opts.url,' ajax is complete');
},
timeout: opts.timeout || 20000
})
}
}
核心是這一句 eval(opts[json.status])(json); 將狀態碼轉換成回調函數,並將json對象傳進去。
調用
LI.POST({
url: LI_ENV.URL.BASE + LI_ENV.API.doPrayerSquareLike,
data: {
prayerSquareId: LI.getUrlParameter('id')
},
isLogin: true,
//isCors: true,//如跨域設置true即可
600: function(json){
console.log("點贊成功");
},
803: function(){
console.log('請登錄后操作');
},
609: function(){
console.log('已點贊');
}
})
跨域Controller
@RequestMapping(value = "cors", method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
public commonResult cors(@RequestParam String url,
@RequestParam(required=false) String params,
HttpServletRequest request,
HttpServletResponse response) throws IOException, URISyntaxException {
LOGGER.info("The request of cors,url:{},params:{}",url,params);
boolean isGet = request.getMethod().toLowerCase().equals("get");
Map<String, String> map = new HashMap<String, String>();
if (!StringUtils.isBlank(params)) {
//有序遍歷
LinkedHashMap<String, String> jsonMap = JSON.parseObject(params, new TypeReference<LinkedHashMap<String, String>>() {
});
for (Map.Entry<String, String> entry : jsonMap.entrySet()) {
map.put(entry.getKey(), entry.getValue());
}
}
String result = null;
try {
if (isGet) {
result = apiService.doGet(MANAGE_URL + url, map);
}else{
HttpResult hr = apiService.doPost(MANAGE_URL + url, map);
result = hr.getData();
}
JSONObject obj = JSONObject.parseObject(result);
try {
Integer status = obj.getInteger("status");
String msg = obj.getString("msg");
return new commonResult(status, msg, obj.get("data"));
} catch (Exception e) {
return commonResult.fail();
}
} catch (Exception e) {
return commonResult.fail();
}
}
核心代碼如上,得到前端傳上來的url,以及解析params,再通過httpClient的形式請求真正的后台地址,其中doPost方法來自 ApiUtil
同時跨域也可以參考以前的文章 jsonp跨域請求
