基于XMLHttpRequest对象封装ajax

3,352 阅读3分钟

这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战

在日常项目中,相信大家经常使用axios来请求数据,它本身就是基于XMLHttpRequest对象来实现的请求库,jquery同样也封装了一个ajax函数,来实现我们的数据请求操作,今天我们来带着大家来实现ajax。什么是Ajax呢?简单的说就是,在不重新加载网页的情况下,AJAX 通过后台加载数据,并在网页上进行显示。

XMLHttpRequest

XHR对象用于与服务器交互,通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。

如何实现一个简单的请求呢,我们先以一个get请求为例,在使用XMLHttpRequest时,我们需要初始化一个实例对象xhr,即

 var xhr = new XMLHttpRequest();

在初始化一个对象后,我们需要告诉Ajax对象要向哪发送请求,以什么方式发送请求,即

// 1)请求方式 2)请求地址
xhr.open('get', 'http://localhost:3000/first');

接着我们需要发送我们的请求如下,值得我们需要注意的是,当他是post方法时,我们应该改成 xhr.send(params);get请求是拼接在url上的。

xhr.send();

最后,我们需要监听我们请求状态的改变,是否完成,成功还是失败

// 获取服务器端响应的数据
xhr.onload = function () {
   console.log(xhr.responseText)
}

除了onload事件外,我们还可以监听onloadend事件,或者onreadystatechange事件,根据request.readyState判断请求状态,具体可以查看MDN: readyState

至此,我们简单的一个get请求就发送成功了,也对 XMLHttpRequest对象有了一点了解。

如何封装一个ajax

讲完 XMLHttpRequest对象,我们就来看看怎么实现一个ajax函数吧,让他能支持我们发送请求,我们就默认大家都使用过了,就不介绍怎么使用了。

我们先来分析一下怎么传参,getpost的请求参数是不同的,还有请求参数格式的问题,比如application/x-www-form-urlencodedapplication/json,这些都是我们需要考虑的;在一个,我们不需要每次都传一些参数,比如methodget时,我们可以不传,默认就是。可以具体来看我们的代码实现。

function ajax(options) {
    // 存储的是默认值
    var defaults = {
        type: 'get',
        url: '',
        data: {},
        header: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        success: function () { },
        error: function () { }
    };

    // 使用options对象中的属性覆盖defaults对象中的属性
    Object.assign(defaults, options);

    // 创建ajax对象
    var xhr = new XMLHttpRequest();
    // 拼接请求参数的变量
    var params = '';
    // 循环用户传递进来的对象格式参数
    for (var attr in defaults.data) {
        // 将参数转换为字符串格式
        params += attr + '=' + defaults.data[attr] + '&';
    }
    // 将参数最后面的&截取掉 
    // 将截取的结果重新赋值给params变量
    params = params.substr(0, params.length - 1);

    // 判断请求方式
    if (defaults.type == 'get') {
        defaults.url = defaults.url + '?' + params;
    }

    /*
        {
            name: 'zhangsan',
            age: 20
        }

        name=zhangsan&age=20

     */

    // 配置ajax对象
    xhr.open(defaults.type, defaults.url);
    // 如果请求方式为post
    if (defaults.type == 'post') {
        // 用户希望的向服务器端传递的请求参数的类型
        var contentType = defaults.header['Content-Type']
        // 设置请求参数格式的类型
        xhr.setRequestHeader('Content-Type', contentType);
        // 判断用户希望的请求参数格式的类型
        // 如果类型为json
        if (contentType == 'application/json') {
            // 向服务器端传递json数据格式的参数
            xhr.send(JSON.stringify(defaults.data))
        } else {
            // 向服务器端传递普通类型的请求参数
            xhr.send(params);
        }

    } else {
        // 发送请求
        xhr.send();
    }
    // 监听xhr对象下面的onload事件
    // 当xhr对象接收完响应数据后触发
    xhr.onload = function () {

        // xhr.getResponseHeader()
        // 获取响应头中的数据
        var contentType = xhr.getResponseHeader('Content-Type');
        // 服务器端返回的数据
        var responseText = xhr.responseText;

        // 如果响应类型中包含applicaition/json
        if (contentType.includes('application/json')) {
            // 将json字符串转换为json对象
            responseText = JSON.parse(responseText)
        }

        // 当http状态码等于200的时候
        if (xhr.status == 200) {
            // 请求成功 调用处理成功情况的函数
            defaults.success(responseText, xhr);
        } else {
            // 请求失败 调用处理失败情况的函数
            defaults.error(responseText, xhr);
        }
    }
}

ajax({
    type: 'post',
    // 请求地址
    url: 'http://localhost:3000/responseData',
    success: function (data) {
        console.log('这里是success函数');
        console.log(data)
    }
})