先看一下JAVA怎么执行一个请求
String url = "http://xxx.xxx.xxx.xxx:xxx/api/pay/recharge";
HashMap map = new HashMap();
map.put("amount", "100");
Request.newInstance(WxPayJson1.class)
.setUrl(url)
.setMethod(Method.POST)
.addParams(map)
.addHeader("X-Requested-With", "XMLHttpRequest")
.addHeader("User-Agent", "aa")
.excute(new SimpleDataCallBack<WxPayJson1>() {
@Override
public void onStart() {
super.onStart();
}
@Override
public void onNext(WxPayJson1 payJson) {
super.onNext(payJson);
Log.e(TAG, payJson.toString());
}
@Override
public void onError(Exception e) {
super.onError(e);
}
@Override
public void onCompleted() {
super.onCompleted();
}
});
我想要把这种写法用到js上面,然后就开始编写JS了。
(本人js小白:》)下面是封装的代码,不代表生产环境使用代码,只做参考。
/**
* Created by itzhu on 2017/8/29.
*/
/*------------CallBack---------------- */
/**
* callback类,网络请求的回调
* 一般来说它需要实现onStart\onNext\onComplete\onerror方法,因为没有接口的概念(当然函数可以作为对象传递,也没必要纠结接口怎么用js实现)
* 想用继承去写,觉得麻烦,就这么写了。
* 这个主要是为了实现链式调用,以及再执行方法前条用一些通用的操作。
* 你也可以根据这个写一个SimpleUiCallBack,如果传递这个callback,在请求前会显示一个dialog,请求完成之后dialog自动消失...请求失败弹出toast等,如果有这些操作,建议再封装一个callback
* callback里面有下面的几个方法即可,因为没有接口设计,不好设计抽象类。
* 这个没有加入TAG字段,如果多个请求使用一个callback不能区分,需要自己定义字段标记,自行设计。
*
* **/
function CallBack() {
this.start = null;
this.next = null;
this.complete = null;
this.error = null;
}
CallBack.prototype = {
constructor: CallBack,
/*------设置方法-----*/
/**
* @param {function()}start
*/
Start: function (start) {
this.start = start;
return this;
},
/**
* @param {function(data)}next
*/
Next: function (next) {
this.next = next;
return this;
},
/**
* @param {function()}complete
*/
Complete: function (complete) {
this.complete = complete;
return this;
},
/**
* @param {function(code,method,url)}error
*/
Error: function (error) {
this.error = error;
return this;
},
/*--------执行方法---------*/
onStart: function () {
if (this.start != null) this.start();
},
onNext: function (data) {
if (this.next != null) this.next(data);
},
onComplete: function () {
if (this.complete != null) this.complete();
},
onError: function (code, method, url) {
if (this.error != null) this.error(code, method, url);
}
};
/*------------------------ShttpDefine------------------------------*/
/**
* HTTP的build方式设置参数信息
* */
function ShttpDefine() {
this.callback = null;//可以不用
this.url = null;
this.method = null;
this.params = {};
this.headers = {};
}
ShttpDefine.prototype = {
constructor: ShttpDefine,
/**
* 请求URL
* @param {string}url
* **/
Url: function (url) {
this.url = url;
return this;
},
/**
* 执行方法get/post/put/delete......
* @param {string}method
* **/
Method: function (method) {
this.method = method;
return this;
},
/**
* 添加请求数据
* @param {JSON}params
* **/
addParams: function (params) {
if (params == null) {
this.params = params;
} else {
this.params = mergeJsonObject(this.params, params);
}
return this;
},
/**
* 添加请求头
* @param {JSON}headers
* **/
addHeaders: function (headers) {
if (headers == null) {
this.headers = headers;
} else {
this.headers = mergeJsonObject(this.headers, headers);
}
return this;
},
/**
* 开始执行这个请求
* @param {CallBack}callback
* */
execute: function (callback) {
this.callback = callback;
SHttp.request(this.url, this.method, this.params, this.data, this.callback);
}
}
/*------------------HttpDefaultConfig-----------------------------*/
/**
* http默认配置
* **/
var HttpDefaultConfig = {
/**请求头配置*/
headers: {
// 'Accept': 'application/json',
//'User-Agent': 'app',
'X-Requested-With': 'XMLHttpRequest',
//'Content-Type': 'application/x-www-form-urlencoded',
'channelToken': 'xxxxxxxxxx',
//'debug': true
},
/*其他配置*/
async: true,
timeout: 3000,
/*以下配置貌似没啥用,因为请求头里面可以完成这些配置*/
dataType: "text",
contentType: "text/plain; charset=UTF-8",
jsonp: "callback" // for query string
}
/**
* 执行类
* */
var SHttp = {
/***
* 相当于全局配置
* */
defaultConfig: HttpDefaultConfig,//默认配置
/**
* 可能有点类似内部类的写法,主要是实现build的设置方式
* */
newInstance: function () {
var shttpDefine = new ShttpDefine();
//shttpDefine.addHeaders(httpDefaultConfig.headers);//设置默认头部
return shttpDefine;
},
/**
* 网络请求的实现类,里面实现网络请求,不管用Ajax/Fetch等
* */
request: function (url, method, params, headers, simpleCallBack) {
simpleCallBack.onStart();
httpx.request({
headers: mergeJsonObject(headers, this.defaultConfig.headers),
async: this.defaultConfig.async,
timeout: this.defaultConfig.timeout,
//dataType: this.defaultConfig.dataType,
//contentType: this.defaultConfig.contentType,
//jsonp: this.defaultConfig.jsonp, // for query string
method: method,
url: url,
data: params,
success: function (data) {
simpleCallBack.onNext(data);
simpleCallBack.onComplete();
},
error: function (method, url) {
simpleCallBack.onError(-1, method, url);
},
ontimeout: function (method, url) {
simpleCallBack.onError(-2, method, url);
}
});
}
}
/**
* 合并两个json对象属性为一个对象
* @param {JSON}jsonbject1
* @param {JSON}jsonbject2
* @returns {JSON}resultJsonObject
* */
mergeJsonObject = function (jsonbject1, jsonbject2) {
var resultJsonObject = {};
for (var attr in jsonbject1) {
resultJsonObject[attr] = jsonbject1[attr];
}
for (var attr in jsonbject2) {
resultJsonObject[attr] = jsonbject2[attr];
}
return resultJsonObject;
};
上面算封装完成了,看一下网络请求怎么写
/**
* 个人喜欢这样的写法,因为JAVA里面也封装了一个写法类似的请求,所以想在js里面也用这种方式
* 总的来说,看一下JAVA的函数式编程,或者知道看一下scala,理解一下方法也可以传递,写js也不算太难。
* js代码可读性差或许是因为它太灵活了,scala的可读性也差,所以有一种特定的写法还是比较好的
* 这里只是一个实践性测试吧,不过如果你也是java开发,你应该也可以把部分通用代码封装成特定易懂的格式,不管语言怎么变动,格式不变就OK了,
* 这个目的是让人一看就知道一个网络请求该怎么写,代码可读性会更好一点,虽然它看起来比较繁琐。
* 引入的时候再用jsCompress压缩一下,或者把httpx和这个文件合并压缩,可能也就10K不到
* */
SHttp.newInstance()
.Url("http://xxx.xxx.xxx:xxxx/api/activity_bid/getProductsDeal")
.Method("post")
.addParams({"pageNo": 1, "pageSize": 3})
.addHeaders({"debug": true})
.execute(new CallBack()
.Start(function () {
console.log("start");
})
.Next(function (data) {
console.log("next->" + data);
})
.Complete(function () {
console.log("complete");
})
.Error(function (code, method, url) {
console.log("error->" + code + method + url);
})
);
这个就完成了,实际代码还没200行。里面用到了httpx这个库:https://github.com/pandao/httpx.js
相当于在这个库上再封装一种写法。如果你会rxjs,使用rxjs封装应该会更好。