先看一下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封装应该会更好。