XMLHttpRequest 是一個客戶端的API,提供了從客戶端與服務端之間傳輸資料的功能。它能通過向一個URL傳送簡單或獲取資料,且並不重新整理頁面,常用於AJAX請求。支援“xml”、"http"、"file"、"ftp"等協議。
以下為一個最簡單的例子:
const xhr = new XMLHttpRequest();
xhr.open("GET","http://example.com",false);
xhr.send();複製程式碼
但實際上,我們開發時,是需要接收請求成功後得到的資料的,如下:
- 這裡需要注意的是,onreadystatechange必須在open方法呼叫前宣告。否則當傳送請求之後是無法重新設定相應的響應事件的
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
console.log('請求成功')
console.log(this.response)
} else if (this.readyState === 1) {
console.log('請求中')
} else {
console.log('請求失敗')
}
}
xhr.open('GET', 'https://www.baidu.com', false);
xhr.send();複製程式碼
接下來,我們來玩點好玩的(非同步與同步)
原始碼如下:
console.log(1)
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
console.log(2)
if (this.readyState === 4 && this.status === 200) {
console.log('請求成功')
} else if (this.readyState === 1) {
console.log('請求中')
} else {
console.log('請求失敗')
}
}
xhr.open('GET', 'https://www.baidu.com', false); // false 改成 true
xhr.send();
console.log(3)複製程式碼
結果如下:
當我們把上文程式碼中的 false 改成 true。結果如下:
究竟是怎麼回事呢?其實XMLHttprequest中的open方法的第三個引數控制的是是否非同步,一開始我們設定成false,也就是表示這是同步執行的命令,導致程式碼阻塞,那麼此時瀏覽器也很懂人情地說了一個warn:
[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check xhr.spec.whatwg.org/.
大致的意思就是說執行同步程式碼會導致程式碼執行的堵塞,影響使用者體驗。當後面我們把false改為true,也很顯然的,列印1之後,馬上列印了3,不像第一次時,等2列印後,才列印3。
把AJAX封裝成Promise物件
這裡,我打算模仿一下axios的使用方法:
axios.get('http://example.com');
axios.post('http://example.com');複製程式碼
Axios類庫
class Axios {
get(url, data = {}) {
return this.XMLHttpRequestObject('GET', url, data);
}
post(url, data = {}) {
return this.XMLHttpRequestObject('POST', url, data);
}
XMLHttpRequestObject(method, url, data) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
console.log('請求成功')
resolve(this.response)
} else if (this.readyState === 1) {
console.warn('請求中')
} else if (this.readyState === 4) {
console.error('請求失敗')
reject('請求失敗')
}
}
if (method === 'GET') {
// 此處對url進行引數拼接
}
xhr.open(method, url, true);
xhr.send(data);
return xhr;
})
}
}複製程式碼
呼叫Axios
const axios = new Axios(); // 新建Axios例項
console.log(await axios.get('https://www.example.com'))
console.log('全部完成')複製程式碼
PS:以上都是沒有考慮IE的情況,以後有空我再填坑