原生JS封装AJAX请求

前言

一直在用jQuery方法来写ajax请求,用的多了,不免对这其中是怎么实现的产生了兴趣,于是乎, 小弟闲来无聊研究了一下原生实现ajax请求,网上看了很多前辈们的关于ajax请求的封装方法, 也借鉴了很多经验,于是乎就出现了小弟的一个原生JS封装ajax的版本,希望大家看了之后能够明白,下面就是我实现的方法,其中的注释很清晰,方便大家的理解。

实现

新建文件夹 ajax.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
!(function (wd) {
wd._$ = new function () {
//ajax模块
let Ajax = {
//ajax模块
init: function (obj) {
//初始化数据
var objAdapter = {
url: obj.url || '',
type: obj.type || 'get',
dataType: obj.dataType || "json",
data: (obj.type && obj.type.toLowerCase() == "get" ? (Ajax.params(obj.data)) : obj.data) || "get",
contentType: obj.contentType || 'application/json',
success: obj.success || function () { },
complete: obj.complete || function () { },
error: obj.error || function (s) {
alert('status:' + s + 'error!');
},
accepts: {
script: 'text/javascript, application/javascript, application/x-javascript',
json: 'application/json',
xml: 'application/xml, text/xml',
html: 'text/html',
text: 'text/plain'
},
async: obj.async ? true : false
}
//通过使用JS随机字符串解决IE浏览器第二次默认获取缓存的问题
return objAdapter;
},
//创建XMLHttpRequest对象
createXHR: function () {
if (window.XMLHttpRequest) { //IE7+、Firefox、Opera、Chrome 和Safari
return new XMLHttpRequest();
} else if (window.ActiveXObject) { //IE6 及以下
var versions = ['MSXML2.XMLHttp', 'Microsoft.XMLHTTP'];
for (var i = 0, len = versions.length; i < len; i++) {
try {
return new ActiveXObject(version[i]);
break;
} catch (e) {
//跳过
console.error(e);
}
}
} else {
throw new Error('浏览器不支持XHR对象!');
}
},
paramsData: function (options) {
function appendQuery(url, query) {
if (query == '') return url
return (url + '&' + query).replace(/[&?]{1,2}/, '?')
}

if (options.data)
options.data = Ajax.params(options.data)
if (options.data && (!options.type || options.type.toUpperCase() == 'GET' || 'jsonp' == options.dataType)) {
options.url = appendQuery(options.url, options.data), options.data = undefined
}
return options;
},
params: function (data) {
var arr = [];
for (var i in data) {
//特殊字符传参产生的问题可以使用encodeURIComponent()进行编码处理
arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));
}
return arr.join('&');
},
callback: function (obj, xhr) {
var result, dataType, error = false;
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { // || (xhr.status === 0 && protocol === 'file:')) {
if (xhr.responseType === 'arraybuffer' || xhr.responseType === 'blob') {
result = xhr.response;
} else {
result = xhr.responseText;
dataType = obj.dataType ? obj.dataType : xhr.getResponseHeader('content-type').split(';', 1)[0];
for (var i in obj.accepts) {
if (obj.accepts.hasOwnProperty(i) && obj.accepts[i].indexOf(dataType) > -1) dataType = i;
}
try {
if (dataType === 'script') {
eval(result);
} else if (dataType === 'xml') {
result = xhr.responseXML
} else if (dataType === 'json' || dataType == "application/json") {
result = result.trim() === '' ? null : JSON.parse(result)
}
} catch (e) {
obj.error && obj.error(e, xhr);
xhr.abort();
}
}
obj.success && obj.success(result, xhr);
} else {
obj.error && obj.error(xhr.statusText, xhr);
}
},
ajax: function (obj) {
if (obj.type && obj.type.toLowerCase() === 'post') {
Ajax.post(obj);
} else {
Ajax.get(obj);
}
},
//post方法
post: function (obj) {
var xhr = Ajax.createXHR(); //创建XHR对象
var opt = Ajax.init(obj);
opt.type = 'post';
if (opt.async === true) { //true表示异步,false表示同步
//使用异步调用的时候,需要触发readystatechange 事件
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) { //判断对象的状态是否交互完成
Ajax.callback(opt, xhr); //回调
}
};
}
//在使用XHR对象时,必须先调用open()方法,
//它接受三个参数:请求类型(get、post)、请求的URL和表示是否异步。
xhr.open(opt.type, opt.url, opt.async);
//post方式需要自己设置http的请求头,来模仿表单提交。
//放在open方法之后,send方法之前。
xhr.setRequestHeader('Content-Type', opt.contentType ? opt.contentType : 'application/x-www-form-urlencoded');
xhr.send(opt.data); //post方式将数据放在send()方法里
if (opt.async === false) { //同步
Ajax.callback(opt, xhr); //回调
}
},
//get方法
get: function (obj) {
var xhr = Ajax.createXHR(); //创建XHR对象
var opt = Ajax.init(obj);
if (opt.async === true) { //true表示异步,false表示同步
//使用异步调用的时候,需要触发readystatechange 事件
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) { //判断对象的状态是否交互完成
Ajax.callback(obj, xhr); //回调
}
};
}
//若是GET请求,则将数据加到url后面
/* opt.url += opt.url.indexOf('?') == -1 ? '?' + opt.data : '&' + opt.data;
opt.url += opt.url.indexOf('?') == -1 ? '?' + ('_=' + (new Date().getTime())) : '&' + ('_=' + new Date().getTime()); */

//在使用XHR对象时,必须先调用open()方法,
//它接受三个参数:请求类型(get、post)、请求的URL和表示是否异步。
xhr.open(opt.type, opt.url, opt.async);
xhr.send(null); //get方式则填null
if (opt.async === false) { //同步
Ajax.callback(opt, xhr); //回调
}
}
};
return Ajax;
}

/**
* fetch get请求
* @param {Object} param
*/
wd.getFetch = function (param) {
if (param.data) {
let paramsArray = [];
//拼接参数
Object.keys(param.data).forEach(key => paramsArray.push(key + '=' + param.data[key]))
if (param.path.search(/\?/) === -1) {
param.path += '?' + paramsArray.join('&')
} else {
param.path += '&' + paramsArray.join('&')
}
}
window.fetch(param.path, {
mode: "no-cors",
type: 'GET',
credentials: "include", //same-origin
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}).then((rep) => rep.json()).then(data => {
param.success && param.success(data);
}).catch(function (error) {
param.error && param.error(error);
});

}
/**
* fetch post请求
* @param {Object} param
*/
wd.postFetch = function (param) {
var fromData = new FormData();
if (param.data) {
for (var key in param.data) {
fromData.append(key, data[key]);
}
}
window.fetch(param.path, {
mode: "cors", //"no-cors",
type: 'POST',
cache: 'default',
credentials: "include", //same-origin
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE',
"Content-Type": "application/json",
"Accept": "application/json"
},
body: fromData || {}
}).then((rep) => rep.json()).then(data => {
param.success && param.success(data);
}).catch(function (error) {
param.error && param.error(error);
});
}

}(window));

在Vue 中的二次封装

新建文件 http.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

import './ajax';
//ajax公共方法
export default {
comAjax(param) {
_$.ajax({
type: param.method || 'post',
data: param.data,
async: param.async != false,
url: param.url || '',
contentType: param.contentType ? 'application/json' : '',
success(data) { // 成功回调
return param.success && param.success(data);
},
error(err) {
utils.view.dismissLoading(); // 关闭loading
return param.error && param.error(err); // error处理
},
});
},
};

在Vue 中的引用---POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
*
* @param param 参数
* @param cb 回调方法
* @returns {*}
*/
apiAppointList(param, cb) {
return api.comAjax({
url: `url/${param.uid}/${param.id}`,
method: 'post',
contentType: 'application/json',
data: JSON.stringify(params),
success(data) {
return cb && cb(data);
},
error(err) {
return utils.toast(err.message);
},
});
},
getAppointList(){
utils.view.showLoading(); // 显示loading
this.apiAppointList(data, result => {
utils.view.dismissLoading() // 关闭loading
if (result.code !== 200) {
return utils.toast(result.message)
}
if (result.data.length < 1){
utils.toast("暂无数据")
}
***
})
},
},

在Vue 中的引用---GET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
*
* @param param 参数
* @param cb 回调方法
* @returns {*}
*/
apiAppointList(param, cb) {
return api.comAjax({
url: `url/${param.uid}/${param.id}`,
method: 'get',
success(data) {
return cb && cb(data);
},
error(err) {
return utils.toast(err.message);
},
});
},
getAppointList(){
utils.view.showLoading(); // 显示loading
this.apiAppointList(data, result => {
utils.view.dismissLoading() // 关闭loading
if (result.code !== 200) {
return utils.toast(result.message)
}
if (result.data.length < 1){
utils.toast("暂无数据")
}
***
})
},
},

结语

封装以上的方法主要是因为原生js传递请求参数比较麻烦,于是乎改良了一下,希望对大家有帮助,喜欢我的文章的话,就给我来个喜欢吧,

---本文结束感谢您的阅读---

本文标题:原生JS封装AJAX请求

文章作者:zhangdongfei

发布时间:2019年05月11日 - 10:32:14

最后更新:2019年05月11日 - 10:41:40

原始链接:http://yoursite.com/2019/05/11/js-ajax/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

请作者喝杯咖啡吧~
0%