AJAX是一种实现在不刷新网页的情况下通过XmlHttpRequest()来访问服务器并根据数据的处理结果按照预期的方式对页面进行修改的技术。
AJAX即Async JavaScript And Xml 是异步的JS和Xml的技术。

AJAX的用法

核心只有4句话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let xhr = new XMLHttpRequest()
xhr.open()
// open有3个参数 xhr.open('method','path',true)
// method 可以是GET POST DELETE PUT 等等 具体参考mdn
// path 就是获取网址的地址
// 第三个参数为boolean 可以选择同步 和 异步 默认为true 为异步
xhr.onreadystatechange = ()=>{
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
console.log('请求成功')
}else if(xhr.status >= 400){
console.log('请求失败')
}
}
}
xhr.send()
// send 可以设置请求体 即请求的第四部分

有2个问题

JS可以设置请求头吗

答案是可以

通过setRequestHeader()的方法可以设置请求头。

设置响应头有2个注意事项:

  1. 设置响应头需要在open()send()之间。

  2. 如设置多行,浏览器会合并成一行。

1
2
3
4
5
let xhr = new XMLHttpRequest()
xhr.open('post','/xxx',true)
xhr.setRequestHeader('Content-Type','application/x-www-from-encoded')
// 具体请看MDN
xhr.send()
通过send()可以设置请求的第四部分即请求体。

一般如果是GET请求,浏览器会屏蔽第四部分,如果是POST请求,浏览器会展示出来。
具体查看方法:

  1. 打开浏览器控制台
  2. 点到Network,点到文件,点击View Source,就可以看到请求头,请求体了。
JS可以读取响应的任何部分吗

答案也是可以的

JS可以通过以下方式获取响应任何部分。
1
2
3
4
5
6
let xhr = new XMLHttpRequest()
xhr.status // 获取状态码
xhr.statusText // 获取状态码描述
xhr.getResponseHeader() // 获取响应头
xhr.getAllResponseHeaders() // 获取所有响应头
xhr.responseText // 获取响应描述即后台的 response.write()中的内容

封装自己的AJAX

第一次封装
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
window.jquery = function(nodeOrSelector){
let nodes = {
0:nodeOrSelector,
length:1
}
nodes.addClass = function(){}
ndoes.text = function(){}
return nodes
}
window.$ = window.jquery
window.jquery.ajax = function(url,method,requestBody,successFn,failFn,headers){
let xhr = new XMLHttpRequest()
xhr.open(method,url)
for(let key in headers){
let value = headers[key]
xhr.setRequestHeader(key,value)
}
xhr.onreadystatechange = ()=>{
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
successfn.call(undefined,xhr.responseText)
}else if(xhr.status >= 400){
failFn.call(undefined,xhr.status)
}
}
}
xhr.send(requestBody)
}

// 调用方法 假设有一个按钮id为button
let button = document.querySector('button')
button.addEventListener(click,(e)=>{
let f1 = (x)=>successFn.call(undefined,x)
let f2 = (x)=>{console.log(x.status)}
window.jquery.ajax('/xxx', 'post', 'a=1&&b=2',f1,f2,null)
})

这个方法设置有一个缺点,传参很乱容易写出别人无法理解的函数比如没有请求体设置请求头
window.jquery.ajax('get','/xxx',null,null,successFn,failFn)这样不好,容易忘,所以来优化一下代码。

第一次优化
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
// 上面全一样
window.jquery.ajax = function(options){
let url = options.url
let method = options.method
let requestBody = options.requestBody
let successFn = options.successFn
let failFn = options.failFn
let headers = options.headers

let xhr = new XMLHttpRequest()
xhr.open(method,url)
for(let key in headers){
let value = headers[key]
xhr.setRequestHeader(key,value)
}
xhr.onreadystatechange = ()=>{
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
successfn.call(undefined,xhr.responseText)
}else if(xhr.status >= 400){
failFn.call(undefined,xhr.status)
}
}
}
xhr.send(requestBody)
}

// 把变量以对象的形式调用 就不会出现上面那种尴尬的形式了
window.jquery.ajax({
'url':'/xxx',
'method':'post',
'requestBody':'a=1&&b=2',
'headers':{
'lee':18 // 可以设置任何请求头
},
// 两个回调函数
'successFn':(x)=>{
f1.call(undefined,x)
f2.call(undefined,x)
},
'failFn':(x)=>{
console.log(x)
console.log(x.status)
console.log(x.responseText)
}
})
第二次优化
1
2
3
4
5
6
7
// 解构赋值
// 把上面6个let 以下面形式 声明
let {url,method,headers,successFn,failFn,requestBody} = options

// 再次优化
// 这样就可以了
window.jquery.ajax = function({url,method,headers,successFn,failFn,requestBody}){}
Promise形式的封装
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
window.jquery.ajax = function({url,method,requestBody,headers}){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest()
xhr.open(method,url)
for(let key in headers){
let value = headers[key]
xhr.setRequestHeader(key,value)
}
xhr.onreadystatechange = ()=>{
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
resolve.call(undefined,xhr.responseText)
}else if(xhr.status >= 400){
reject.call(undefined,xhr.status)
}
}
}
xhr.send(requestBody)
})
}

// 调用
window.jquery.ajax({
'url':'/xxx',
'method':'post',
'requestBody':'a=1&&b=2',
'headers':{
'lee':18 // 可以设置任何请求头
}
}).then(
(text)=>{console.log(text)}, // resolve
(xhr)=>{console.log(xhr)} // reject
)

总结

以上就是我个人封装AJAX的方法。
同时我们还可以通过JSONP、img、iframe、link、的方法来与后台沟通刷新页面数据。

__END__

o0Chivas0o
文章作者:o0Chivas0o
文章出处自己实现AJAX
作者签名:Rich ? DoSomethingLike() : DoSomethingNeed()
版权声明:文章除特别声明外,均采用 BY-NC-SA 许可协议,转载请注明出处