關於原生 XMLHttpRequest 發送請求可以做的一些事情。
目前 XMLHttpRequest 實列是被所有瀏覽器支持的。
首先創建一個 XHR 對象實例。
const request = new XMLHttpRequest()
之後可以配置一些 返回值類型、超時時間、跨域請求攜帶COOKIE之類的。
request.responseType = responseType
request.timeout = timeOut
request.withCredentials = withCredentials
調用 XHR 對象的 open() 方法, 傳入請求類型‘GET'/'POST' 之類的, 請求地址、 async 的值爲 boolean 類型的。
request.open(method, url, true)
之後可以爲 XHR 對象 添加時間處理器 onreadystatechange , 可以針對請求的一些狀態來做一些處理。
request.onreadystatechange = function handleLoad() {
if (request.readyState !== 4) {
return
}
if (request.status === 0) {
return
}
// 更多的一些騷操作
}
還有一些 錯誤處理、超時處理之類的
// 錯誤處理
request.onerror = function handleError() {
reject(createError('Network Error', config, null, request))
}
// 超時處理
request.ontimeout = function handleTimeout() {
reject(createError(`Timeout of ${timeOut} ms exceeded`, config, 'ECONNABORTED', request))
}
然後會做一點簡單的 xsrf 防禦之類的,關於xsrf 防禦,通常是服務端在客戶端種下一個 cookie ,cookie 的值是後端出的,然後客戶端在發請求的時候, 在請求頭裏面添加上與後端協定好的字段,把 cookie 的值填充進去,這樣後端收到請求的時候會看看請求頭裏面有沒有協定好的字段,然後值是不是對的上,就可以防禦到跨站攻擊拉。
// 這裏先讀到 cookie 然後把 cookie 添加到 headers 的配置裏面,後面配置頭部的時候會一起加進去
if ((withCredentials || isURLSameOrigin(url!)) && xsrfCookieName) {
const xsrfValue = cookie.read(xsrfCookieName)
if (xsrfValue && xsrfHeaderName) {
headers[xsrfHeaderName] = xsrfValue
}
}
配置頭部, 因爲之前有一個存放 Header 配置的 headers 對象,所以在 xsrf 防禦的時候會先把配置的 header 名字和值加到 headers 對象裏面,現在直接循環出來統一配置就好拉。
Object.keys(headers).forEach(name => {
// 判斷一下 如果 data = null 就沒必要配置 headers 的 content-type 了
if (data === null && name.toLowerCase() === 'content-type') {
delete headers[name]
} else {
request.setRequestHeader(name, headers[name])
}
})
最後發送這個請求
request.send(data)
這個請求自己封裝了一下,返回一個 Promise 對象,所以會出現 reject 方法, resolve 的調用在 onreadystatechange 裏面做處理,請求狀態成功了之後會去調 resolve 的,示例代碼裏面只是沒貼出來,這裏只是記錄一下 XHR 對象發送請求大概要做的步驟。
那之後可以根據 Promise 鏈式調用的特性去做請求攔截和響應攔截,在加上取消請求的方法,還有上傳下載的監控之類的,最後能夠得到一個 小Axios........
其實上面的代碼也是參考了 Axios 做的一個封裝。