curTain

简单的封装一个 ajax:

  1. 自动处理参数
  2. 支持 get 和 post
  3. 支持取消操作

1. 基于 XMLHttpRequest 封装

XMLHttpRequest 相关信息请参考:MDN–XMLHttpRequest

XMLHttpRequest 对象主要的属性:

1.1 原生 XHR 创建步骤

总共分 5 步:

  1. 第一步:使用 new XMLHttpRequest() 创建 XHR 实例
  2. 第二步:使用 xhr.open() 创建一个请求,并初始化相关 http 请求信息
  3. 设置请求头
  4. 设置响应 http 状态变化的函数
  5. 调用 send 方法,发送 http 请求

整体结构:

1
2
3
4
5
6
7
8
9
10
function myAjax(obj) {
this.url = obj.url || '';
this.type = obj.type || 'GET';
this.data = obj.data || {};
this.success = obj.success || null;
this.error = obj.error || null;
this.xhr = new XMLHttpRequest();
}
myAjax.prototype.send = function () {};
myAjax.prototype.abort = function () {};

完成结果:

ajax ---- XMLHttpRequest
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
function myAjax(obj) {
this.url = obj.url || '';
this.type = obj.type || 'GET';
this.data = obj.data || {};
this.success = obj.success || null;
this.error = obj.error || null;
this.xhr = new XMLHttpRequest();
}

myAjax.prototype.send = function () {
// 将数据取出来 以 key=value 的形式保存到数组中,方便后续操作
let dataArr = [];
for (let key in this.data) {
dataArr.push(key + '=' + this.data[key]);
}
if (this.type === 'GET' || this.type === 'get') {
this.url = this.url + '?' + dataArr.join('&');
// 删除尾部的 ?,当 data 为空的时候会多出来 ?
this.xhr.open(this.type, this.url.replace(/\?$/g, ''), true);
this.xhr.send();
}
if (this.type === 'POST' || this.type === 'post') {
this.xhr.open(this.type, this.url, true);
this.xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
this.xhr.send(dataArr.join('&'));
}
// 使用箭头函数 将 this 指向当前对象
this.xhr.onreadystatechange = () => {
if (
this.xhr.readyState === 4 &&
// 200 是请求成功,304 重定向使用缓存资源
(this.xhr.status === 200 || this.xhr.status === 304)
) {
if (this.success && this.success instanceof Function) {
var res = this.xhr.responseText;
if (typeof res === 'string') {
this.success(JSON.parse(res));
}
}
}
};
};
myAjax.prototype.abort = function () {
console.log('已经取消请求...');
this.xhr.abort();
};

2. 基于 fetch 封装

若果你不知道 fetch 的使用,请参考

  1. MDN-fetch 文档
  2. MDN-fetch 使用相关

fetch 第二个参数选项:

  1. method: 请求使用的方法,如 GET、POST。
  2. headers: 请求的头信息,形式为 Headers 的对象或包含 ByteString 值的对象字面量。
  3. body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
  4. mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
  5. credentials: 请求的 credentials,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie , 必须提供这个选项, 从 Chrome 50 开始, 这个属性也可以接受 FederatedCredential 实例或是一个 PasswordCredential 实例。
  6. cache: 请求的 cache 模式: default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached 。
  7. redirect: 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在 Chrome 中,Chrome 47 之前的默认值是 follow,从 Chrome 47 开始是 manual。
  8. referrer: 一个 USVString 可以是 no-referrer、client 或一个 URL。默认是 client。
  9. referrerPolicy: 指定了 HTTP 头部 referer 字段的值。可能为以下值之一: no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url 。
  10. integrity: 包括请求的 subresource integrity 值
  11. signal: 用于取消请求
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
function myFetch(obj) {
this.url = obj.url || '';
this.type = obj.type || 'GET';
this.data = obj.data || {};
this.success = obj.success || null;
this.error = obj.error || null;
// 用于取消 fetch 请求
this.controller = new AbortController();
}

myFetch.prototype.send = function () {
// 将数据取出来 以 key=value 的形式保存到数组中,方便后续操作
let dataArr = [];
for (let key in this.data) {
dataArr.push(key + '=' + this.data[key]);
}
if (this.type === 'GET' || this.type === 'get') {
this.url = this.url + '?' + dataArr.join('&');
// 删除尾部的 ?,当 data 为空的时候会多出来 ?
fetch(this.url.replace(/\?$/g, ''), {
mode: 'cors',
method: 'GET',
signal: this.controller.signal,
})
.then(res => {
return res.json();
})
.then(resObj => {
this.success(resObj);
});
}
if (this.type === 'POST' || this.type === 'post') {
fetch(this.url, {
mode: 'cors',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: dataArr.join('&'),
method: 'POST',
signal: this.controller.signal,
})
.then(res => {
console.log('新鲜的数据:', res);
return res.json();
})
.then(resObj => {
this.success(resObj);
});
}
};

myFetch.prototype.abort = function () {
console.log('取消请求--');
this.controller.abort();
};

3. 总结

XMLHttp
使用原生 XMLHttpRequest 创建 ajax 的步骤分 5 步,一定要记住,

  1. 使用 new XMLHttpRequest() 创建 xhr 实例
  2. 调用 open 方法初始化请求信息
  3. 设置 请求头
  4. 设置请求响应函数
  5. 调用 send 方法发送请求

4. 关于发送文件和图片

发送文件和图片,需要搭配 FormData

直接将 FormData 作为参数发送即可。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 获取文件放入 FormData
var formdata = new FormData();
var elFile = document.getElementById('myfile');
elFile.addEventListener('change', () => {
formdata.append('file', elFile.files[0]);
// 调用发送文件
sendFile();
});
// 创建 xhr
var xhr = new XMLHttpRequest();
xhr.open('post', 'http://***/uploadImage');
xhr.onreadystatechange = function () {
if (xhr.status === 200 && xhr.readyState === 4) {
console.log('请求成功----');
console.log(xhr.response);
}
};
function sendFile() {
xhr.send(formdata);
}

5. 参考材料

MDN–XMLHttpRequest

MDN-fetch 文档

创建 ajax 过程

AJAX 实现步骤,XMLHttpRequest 对象的方法


 评论