之前学习了JSONP可以发送请求去获取数据,JSONP传送门然后通过callback来异步的执行我们预先准备好的函数。
可是JSONP只能发送get请求,这是不是太单一了?需求很多的变化,对于复杂一点的需求的话,无法满足,所以我们来试试用AJAX来实现跨域。
开工
先实现一个点击按钮发送一个请求,这里就需要介绍了一个WEB的API:XMLHttpRequest,MDN解释:它为客户端提供了在客户端和服务器之间传输数据的功能。提供一个通过URL来获取数据的简单方式,并且不会使整个页面刷新。
下面就用这个只是做一个简单的实现:点击一个按钮,发送一个请求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button id="button">点我</button>
<script>
button.addEventListener('click', () => {
let request = new XMLHttpRequest()
request.open('get', '/xxx',) //使用open带入url和一个请求
request.setRequestHeader('Pomelo', '18')
request.send() //发送请求
request.onreadystatechange = () => {
if(request.readyState === 4){
if(request.status >= 200 && request.status < 300){
let string = request.responseText
let obj = window.JSON.parse(string)
console.log(request.getAllRequestHeaders)
console.log(obj)
}else if(request.status >= 400){
console.log('请求失败')
}
}
}
})
</script>
</body>
</html>
readystate
这样就可以实现一个异步的get请求。onreadystatechage监听readystate的变化,用一个函数来处理这个变化。
这里需要列举一下readystate的数值及其含义。
readystate |
状态 |
描述 |
0 |
UNSENT(未打开) |
open()方法还未被调用 |
1 |
OPENED(未发送) |
open()方法已经被调用 |
2 |
HEADERS_RECEIVED(已获取响应头) |
send()方法已经被调用,响应头和响应状态已经返回 |
3 |
LOADING(正在下载响应体) |
响应体下载中;responseText 中已经获取了部分数据 |
4 |
DONE(请求完成) |
整个请求过程已经完毕 |
目前来这个实现还不错,但是每次调用就需要创建一个按钮去发请求。发请求。发请求。这样不会很麻烦吗?我们模仿JQuery那样试试看:
window.jquery.ajax = function(options){
let url = options.url
let method = options.method
let body = options.body
let header = options.header
let success = options.successFn
let fail = options.failFn
let request = new XMLHttpRequest()
request.open(method, url) //在get请求下chrome 默认不显示request的第四部分
for(let key in header){
let value = header[key]
request.setRequestHeader(key, value)
}
request.send(body)
request.onreadystatechange = () => {
if(request.readyState === 4){
if(request.status >= 200 && request.status < 300){
let string = request.responseText
success.call(undefined, string)
}else if(request.status >= 400){
fail.call(undefined, request)
}
}
}
}
这样一做,咱们就可以使用这样的形式调用:
jquery.ajax({
url: '/xxx',
method: 'get',
body: 'hello',
header: 'Pomelo',
success: successFn,
fail: failFn
})
使用ES6特性来优化
这样还不错,如果加上我们ES6的新特性,实现会更加优美:
window.jquery.ajax = function({url, method, body, header}){ //ES6 解构赋值
return new Promise(function(resolve, reject){ //Promise的特性,不用带入success和fail函数。
let request = new XMLHttpRequest()
request.open(method, url) //在get请求下chrome 默认不显示request的第四部分
for(let key in header){
let value = header[key]
request.setRequestHeader('ni', 'hao')
}
request.onreadystatechange = () => {
if(request.readyState === 4){
if(request.status >= 200 && request.status < 300){
let string = request.responseText
resolve.call(undefined, string)
}else if(request.status >= 400){
reject.call(undefined, request)
}
}
}
request.send(body)
})
}
这样就完成了优美的ajax的实现。调用如下:
jquery.ajax({
url: '/xxx',
method: 'post',
body: 'hello everyone',
header: {
'Pomelo': '18',
'Hello': '18'
}
}
}).then(
(xx) => { console.log(xx) },
(xx) => { console.log(xx) }
)
这样是不是就好看许多,简单的就实现了一个ajax。