AJAX第二部
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)
,並且可以多重呼叫。