有了XMLHttpRequest,前後端們終於過上了幸福的生活

A0150315發表於2018-09-17
  • 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)複製程式碼

結果如下:

xmlhttprequest

當我們把上文程式碼中的 false 改成 true。結果如下:

xmlhttprequest

究竟是怎麼回事呢?其實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的情況,以後有空我再填坑


相關文章