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
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
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对象的方法


 评论