有了XMLHttpRequest,前后端们终于过上了幸福的生活

816 阅读2分钟
  • 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的情况,以后有空我再填坑