# 手写ajax
- 这个概念其实作为前端开发在熟悉不过了
- 写此文只是回顾了解$.ajax的使用等
- 本文只是一个mini版本的 基于xhr构造
原生调用方法
我这里截取测试案例某一段具体可以看源码
const _ajax = $.ajax({
context: oTest, //改变this指向为otest这个div
type: 'post',
// contentType: 'application/json', //发送到服务器的数据类型。
// beforeSend: function (body) {
// console.log('body', body);
// return body;
// },
// ifModified: true, //设置http请求缓存 则只有当服务器端的内容与上次请求不一样时,才会发出本次请求
headers: {
//指定HTTP请求的头信息。
a: 1
},
dataType: 'json', //dataType设置你收到服务器数据的格式。
url: 'https://www.fastmock.site/mock/3277f26b72e3b8aa6de012d30c06ce3f/api/prodcut#!method=POST&queryParameters=%5B%5D&body=%7B%0A+%22id%22%3A+1%0A%7D&headers=%5B%5D',
data: {
id: 1
},
success: function (res) {
console.log($(this).html(res.desc || 'hello'));
console.log('res', res);
},
error: function (e) {
// 抛错的钩子函数
}
});
_ajax上面还有一些方法诸如abort等
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
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
手写mini版ajax
/**
* 封装一个ajax
*
*
*/
function stringGetParams(url, params) {
return Object.keys(params).reduce((prev, nextKey) => {
const quot = prev.includes('?') ? '&' : '?';
prev += `${quot}${nextKey}=${params[nextKey]}`;
return prev;
}, url);
}
class MyAjax {
constructor(options) {
this.options = this.initOption(options);
this.initRequest();
}
static onXHRStateChange(options = this.options) {
// const that = this;
// readyState五个状态
// 0:未初始化(Uninitialized)。尚未调用 open()方法。
// 1:已打开(Open)。已调用 open()方法,尚未调用 send()方法。
// 2:已发送(Sent)。已调用 send()方法,尚未收到响应。
// 3:接收中(Receiving)。已经收到部分响应。
// 4:完成(Complete)。已经收到所有响应,可以使用了。
return function () {
// console.log('MyAjax.xhr--init', MyAjax.xhr);
if (MyAjax.xhr.readyState === 4) {
options.complete && options.complete();
if (MyAjax.xhr.status === 200) {
// console.log('MyAjax.xhr-success', MyAjax.xhr);
options.success && options.success(MyAjax.xhr.responseText);
} else {
// console.log('MyAjax.xhr-error', MyAjax.xhr);
options.error &&
options.error(MyAjax.xhr, MyAjax.xhr.status, MyAjax.xhr.statusText);
}
}
}.bind(this);
}
static xhr = new XMLHttpRequest();
initRequest() {
const { type, data, url, success, error, complete } = this.options;
const isGet = type.toLowerCase() === 'get';
if (isGet) {
MyAjax.getMethod(url, data, success, error, complete);
} else {
MyAjax.postMethod(url, data, success, error, complete);
}
}
static getMethod(url, params, success, error, complete) {
console.log('this', this);
const finalUrl = stringGetParams(url, params);
let combineOptions = {
url: finalUrl,
type: 'get',
success,
error,
complete
};
this.options = this.options
? {
...this.options,
combineOptions
}
: combineOptions;
MyAjax.xhr.open('get', finalUrl);
MyAjax.xhr.onreadystatechange = this.onXHRStateChange();
MyAjax.xhr.send();
return MyAjax.xhr;
}
static postMethod(url, params, success, error, complete) {
// console.log('params', params);
const finalData = JSON.stringify(params || {});
let combineOptions = {
url,
type: 'post',
data: finalData,
success,
error,
complete
};
this.options = this.options
? {
...this.options,
combineOptions
}
: combineOptions;
// console.log('finalData', finalData);
MyAjax.xhr.open('post', url);
MyAjax.xhr.setRequestHeader('Content-type', 'application/json'); //默认配置
MyAjax.xhr.onreadystatechange = this.onXHRStateChange();
MyAjax.xhr.send(finalData);
return MyAjax.xhr;
}
initOption(options) {
options.type = options.type.toUpperCase() || 'GET';
options.async ||= true;
options.data ||= {};
options.dataType ||= 'JSON';
options.timeout ||= 10000;
options.complete ||= function () {};
options.success ||= function () {};
options.error ||= function () {};
return options;
}
abort() {
if (MyAjax.xhr) {
MyAjax.xhr.abort();
MyAjax.xhr = null;
}
}
}
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
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
这里我截取一段代码使用