XHR(XMLHttpRequest) 實踐
簡介
XMLHttpRequest(通常縮寫XHR) 是一個 API,它為用戶端提供了在用戶端和伺服器之間傳輸資料的功能。它提供了一個通過 URL 來擷取資料的簡單方式,并且不會使整個頁面重新整理。這使得網頁隻更新一部分頁面而不會打擾到使用者。XMLHttpRequest 在 AJAX 中被大量使用。
Fetch API 提供了一個擷取資源的接口(包括跨域)。
XHR
第一步,建立http請求
warning!: 本文已不再處理ie6-xhr對象的相容性問題
建立一個http請求也是需要提前做一些準備工作的。
- 首先,就是要建立一個xhr對象,這是我們實作AJAX的核心。
// 建立一個xhr對象
const xhr = new XMLHttpRequest()
console.log('test', xhr)
建立完這個對象之後,我們可以在控制台看到這個對象的詳細資訊了。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX9MGROpXTE5UeNRVT3V1MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jNxEDN0YTN5AjMwgDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
- 其次,必須提前聲明一個接收服務端資料的處理函數
// 建立一個xhr對象
const xhr = new XMLHttpRequest()
// 聲明函數,處理服務端的響應資料
xhr.onreadystatechange = res =>{
console.log('res', res)
}
console.log('test', xhr)
- 聲明完處理函數之後,我們需要設定http請求的相關參數
// 建立一個xhr對象
const xhr = new XMLHttpRequest()
// 聲明函數,處理服務端的響應資料
xhr.onreadystatechange = res =>{
console.log('res', res)
}
// 向伺服器請求目标url中的資料檔案
xhr.open('GET', 'http://yyweb.yystatic.com/pc/images/default_portrait.png?20160616', true)
xhr.send()
此時,我們可以看到處理伺服器的回調函數(onreadystatechange),一共被執行了四次。
為什麼會調用四次?我們後面會講到。
第二步,處理服務端資料
通過第一步,我們就可以通過浏覽器發送最基本的request請求了。接下來,我們就準備處理從服務端擷取到的資料資訊了。
還記得,上面我們曾經聲明過的onreadystatechange函數嗎?這就是我們用來處理服務端資料的函數。那麼,我們應該如何正确處理這些資料請求呢?
我們先來看下面的代碼,xhr.onreadystatechange函數中xhr對象的幾種狀态。
// 建立一個xhr對象
const xhr = new XMLHttpRequest()
// 聲明函數,處理服務端的響應資料
xhr.onreadystatechange = res =>{
console.log(`res: ${res}, status: ${xhr.status}, readyState: ${xhr.readyState}`)
}
// 向伺服器請求目标url中的資料檔案
xhr.open('GET', 'http://yyweb.yystatic.com/pc/images/default_portrait.png?20160616', true)
xhr.send()
我們可以看到,
xhr.readyState
傳回了四種不同的狀态。
下面,就來介紹一下這四種狀态的含義:
- 0 request請求還未初始化
- 1 loading 或者與伺服器連接配接中
- 2 loaded 或者伺服器接收到request請求
- 3 建立連接配接或者服務端處理request
- 4 建立完畢或者請求處理完成準備發送response
xhr.status
200代表服務端成功接收到請求。
了解完以上概念之後,我們再來梳理下面的邏輯
// 建立一個xhr對象
const xhr = new XMLHttpRequest()
// 聲明函數,處理服務端的響應資料
xhr.onreadystatechange = res =>{
console.log(`status: ${xhr.status}, readyState: ${xhr.readyState}`)
if (xhr.status === ) {
// 服務端狀态碼: 200 ok 表示請求成功
if (xhr.readyState === ) {
// 準備接收服務端資料
console.log(`status: ${xhr.readyState}, res: ${JSON.stringify(res)}`)
}
} else {
// 0: 準備發送請求
// 400 Not Found or 500 服務端錯誤
}
}
// 向伺服器請求目标url中的資料檔案
xhr.open('GET', 'http://yyweb.yystatic.com/pc/images/default_portrait.png?20160616', true)
xhr.send()
最終,我們成功發起請求從服務端擷取了一張圖檔資料。
第三步,封裝AJAX
為了日常開發使用,我們将AJAX封裝成一個函數庫,便于今後可以随時使用。
- 首先,進行最基本的包裝。将我們上述的代碼放入到一個函數中進行簡單封裝。
const ajax = () => {
// 建立一個xhr對象
const xhr = new XMLHttpRequest()
// 聲明函數,處理服務端的響應資料
xhr.onreadystatechange = res =>{
console.log(`status: ${xhr.status}, readyState: ${xhr.readyState}`)
if (xhr.status === ) {
// 服務端狀态碼: ok 表示請求成功
if (xhr.readyState === ) {
// 準備接收服務端資料
console.log(`status: ${xhr.readyState}, res: ${JSON.stringify(res)}`)
}
} else {
// : 準備發送請求
// Not Found or 服務端錯誤
}
}
// 向伺服器請求目标url中的資料檔案
xhr.open('GET', 'http://yyweb.yystatic.com/pc/images/default_portrait.png?20160616', true)
xhr.send()
}
ajax()
- 然後,為了讓我們封裝的ajax庫能夠适配各種生産環境,這就需要我們動态傳入參數進行配置。