AJAX闲聊….
请求四个部分的设置&响应四个部分的获取
一个http请求包括以下四部分:
第一部分包括请求的method,url以及请求所使用的协议和版本号,比如GET /xxx HTTP/1.1
。
第二部分是请求头,一堆key和value,比如Host: www.baidu.com
,Accept: text/html
,Content-Type: application/x-www-form-urlencoded
等一些header的信息。
第三部分是一个回车,主要作用就是用来区分第二部分和第四部分。
第四部分是请求的内容,即消息主体。一般GET请求是不包含内容的,但是并不一定没有内容,只是就算你有内容也没有用,提交了没人看也是白瞎。但是POST请求是有request body的,内容就是POST提交给服务器的一些数据。数据格式基本上是key1=value1&key2=value2
这种,比如user=wcy&password=123
。
前边我们知道,使用AJAX发送请求有几个必要的步骤:
let request = new XMLHttpRequest()
request.open('method', 'url')
request.onreadystatechange = function(){
if(request.readyState === 4){
console.log('传输完了')
if(request.status >= 200 & request.responseStatus <=300){
console.log('success')
}else if(request.status >= 400){
console.log('fail')
}
}
}
request.send()
请求的第一部分,method和请求的路径url在request.open()
里边进行配置。
请求的第二部分,key,value使用的方法不在上边,但是并不是没有。request.setRequestHeader(key,value)
就是用来设置请求的头部信息的。
请求的第三部分是一个回车,自是不必说了。
至于第四部分请求的内容,使用request.send()
设置,比如request.send('user=wcy&psw=123')
。
一个http响应包括以下四个部分:
第一部分包括协议名版本号,响应的状态码和状态码对应的字符串。比如HTTP/1.1 200 OK
。
第二部分包括响应头,也是一堆key、value。比如说Content-Type: text/html
。
第三部分同样是一个回车。
第四部分是服务器返回给浏览器的数据,比如说html文件。
AJAX对于响应的获取:
第一部分响应的状态码可由request.status
得到,状态码对应的字符串可由request.statusText
得到。
第二部分的响应头可以由request.getResponseHeader('Content-Type')
得到指定的key对应的value,也可以通过request.getAllResponseHeaders()
得到所有的key和value。
第三部分回车不提。
第四部分由request.responseText
可以得到。
tips:
1. AJAX只是获取响应头,响应头是由服务器设置的。
2. 关于readyState和status的联系。
readyState表示的是浏览器AJAX请求发送的状态,status表示的是服务器响应的状态码。
在send方法调用之后,readyState的状态变成了2,此时服务器响应的头部以及状态码status可以被浏览器获取到。所以此时你能知道status是200还是404或者是其他的。
另一种特殊的情况是跨域并且被拒绝,如果是这样的话,readyState还是一样会经历从0到4的五个过程,但是得不到服务器的响应。也因此这种情况下status始终没有值。
AJAX的封装
所谓的封装,就是把那些实现某个功能的代码放到一块,然后暴露出接口让别人能轻松地使用这个功能。这里是一个AJAX的封装。
window.jQuery.ajax = function(method, url, body, successFn, failedFn){
let request = new XMLHttpRequest()
request.onreadystatechange = () => {
if(request.readyState === 4){
if(request.status >= 200 && request.status <= 300){
successFn.call(undefined, 'success')
}else if(request.status >=400){
failedFn.call(undefined, 'failed')
}
}
}
request.open(method, url)
request.send(body)
}
如果只是这样的话有一个问题,调用这个函数的时候你必须知道这些参数的意义和顺序,这是一件很要命的事情,一天两天还能记住,时间长的话就……而且如果是这样的话,你要是不想写参数body,那你就必须传入一个null。
所以我们可以换一个思路,比如,传入一个对象。
window.jQuery.ajax = function(option){
let method = option.method
let url = option.url
let body = option.body
let successFn = option.successFn
let failedFn = option.failedFn
...
}
但是这么长的一串赋值就很不好看了,可以使用ES6的解构赋值,把它们简化成这样
window.jQuery.ajax = function(option){
let {method, url, body, successFn, failedFn} = option
...
}
不过这还不是最简形式,既然是要把对象option赋值给那一堆,那你可以直接省去option,变成这样
window.jQuery.ajax = function({method, url, body, successFn, failedFn}){
...
}
如果传入的参数需要是一个对象,那么调用的时候可以直接传入一个对象。
let obj = {
method: 'POST',
url: '/xxx' ,
body: 'user=wcy&psw=123',
successFn: function(message){console.log(message)},
failedFn: function(message){console.log(message)}
}
window.jQuery.ajax(obj)
至此我们的ajax封装完成。
promise是什么
上边我们封装的ajax里边,如果操作成功的话调用的是successFn,失败的话调用的是failedFn。但这只是我们的习惯,对于别人,可能喜欢直接用success和failed,或者是其它的。promise就是一个用来把它们统一的东西,或者说是规则。
在真正的jQuery里边,你可以使用下边的代码来写成功和失败的时候需要执行的函数。
$.ajax({
url: '/xxx',
method: 'GET'
}).done(
()=>{console.log('成功')}
).fail(
()=>{console.log('失败')}
)
也可以直接使用.then()
像下边这样
$.ajax({
url: '/xxx',
method: 'GET'
}).then(
()=>{console.log('成功')},
()=>{console.log('失败')}
)
可以看见的是上边两种方法都有一个共同之处——没有函数名。不需要函数名的话可以帮我们避免很多问题,比如少想一个函数名。并且,有利于规范化操作。并且在这个时候你如果想要在成功之后调用多个函数的话只需要继续使用.then()
即可。而不使用这个方法的话你必须把两个函数一个函数里边进行调用….
是的,这就是promise,一个确定函数形式的规范,成功就调第一个函数,失败就调第二个函数。
promise是window下的全局变量,大致形式如下:
window.Promise = function(fn){
//...
return {
then: function(){}
}
}
ajax返回了一个promise实例,这个实例有then属性。
如果将我们前面封装的ajax用promise改装一下,那就是下边的样子:
window.jQuery.ajax = function({method, url, body}){ //解构赋值
return new Promise(function(resolve, reject){
let request = new XMLHttpRequest()
request.onreadystatechange = () => {
if(request.readyState === 4){
if(request.status >= 200 && request.status <= 300){
resolve.call(undefined)
}else if(request.status >=400){
reject.call(undefined)
}
}
}
request.open(method, url)
request.send(body)
})
}
调用的时候可以直接使用then了。
button.addEventListener('click', () => {
let obj = {
method: 'POST',
body: 'user=wcy&psw=123',
url: '/xxx'
}
jQuery.ajax(obj).then(
()=>{alert('success')},
()=>{alert('failed')}
)
})
返回一个promise的实例,这个实例的参数必须是一个函数,这个函数又有两个参数,分别是resolve和reject,一个用于成功的时候执行,另一个用于失败的时候执行。调用的时候直接使用.then(fn1, fn2)
,并且可以多重调用。