发起请求并处理响应:`XHR` 与 `axios` 使用指南来啦😊~

1,035 阅读5分钟

又又又要长脑子呐😊~ 了解到通过发起HTTP请求并在不刷新页面的情况下更新页面内容是一种常见的需求。学习使用XMLHttpRequestaxios 来实现,现在进行对比两者,比较项目使用时候的优缺点,文末使用表格进行对比学习

1. 使用 XHR 实现

image.png 下面是一个使用 XMLHttpRequest 发起GET请求并处理服务器响应的示例:

    <p class="my-p"></p>
    <script>
        // 创建一个新的 XMLHttpRequest 对象
        const xhr = new XMLHttpRequest();
        
        // 配置请求
        xhr.open('GET', 'http://hmajax.itheima.net/api/province');
        
        // 监听 loadend 事件,无论成功还是失败都会触发
        xhr.addEventListener('loadend', () => {
            if (xhr.readyState === 4 && xhr.status === 200) {
                try {
                    // 将响应字符串解析为 JSON 对象
                    const data = JSON.parse(xhr.response);
                    console.log(data); // 打印整个响应数据
                    document.querySelector('.my-p').innerHTML = data.list.join('<br>');
            } catch {
                console.error('请求失败:', xhr.statusText);
                document.querySelector('.my-p').innerHTML = '请求失败,请稍后再试';
            } }
        });
        xhr.send(); // 发送请求
    </script>

在这个例子中,我们首先创建了一个 XMLHttpRequest 对象,然后配置了一个GET请求来获取省份信息。我们监听了 loadend 事件,该事件在请求完成时触发,无论是成功还是失败。为了确保只处理成功的响应,我们检查了 xhr.readyStatexhr.status。如果请求成功,我们将服务器返回的JSON数据解析为JavaScript对象,并将 data.list 中的内容以换行符分隔的方式插入到页面中的 <p> 元素内。 image.png

看得出XRH还是很独立,依赖性比较小

2. 使用 axios 实现

axios 是一个基于Promise的HTTP客户端库,它简化了HTTP请求的发送过程,提供了更简洁的API和更好的错误处理机制。axios 还支持自动转换JSON数据、取消请求、拦截器等功能,使得开发更加高效和灵活。

下面是一个使用 axios 发起GET请求并处理服务器响应的示例:

    <p class="my-p"></p>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script>
        // 使用 axios 发起 GET 请求,get不用写
        axios({
            url: 'http://hmajax.itheima.net/api/area',
            params: {
                pname: '江西省',
                cname: '南昌市'
            }
        }).then(res => {
            // 打印整个响应数据
            console.log(res);
            console.log(res.data.list);

            // 获取目标元素
            let p = document.querySelector('.my-p');

            // 检查 res.data.list 是否存在且非空
            if (res.data.list && res.data.list.length > 0) {
                // 将列表项用 `<br>` 标签分隔后插入到页面中
                p.innerHTML = res.data.list.join('<br>');
            } else {
                p.innerHTML = '未找到相关数据';
            }
        }).catch(error => {
            console.error('请求失败:', error);
            p.innerHTML = '请求失败,请稍后再试';
        });
    </script>

在这个例子中,我们使用 axios 发起了一个GET请求,传入了查询参数 pnamecname,用于获取江西省南昌市的地区信息。axios 自动处理了JSON解析,并通过 .then() 方法处理成功的响应,通过 .catch() 方法处理错误。我们还添加了一些额外的逻辑来确保只有在 res.data.list 存在且非空的情况下才进行页面渲染,否则显示提示信息。 image.png

axios设置拦截器

axios 的一个强大特性是它的拦截器功能。拦截器允许你在请求发送之前或响应接收之后对请求或响应进行预处理或后处理。这对于全局配置、日志记录、身份验证等场景非常有用。

例如,你可以设置一个请求拦截器来自动添加认证头,或者设置一个响应拦截器来处理全局的错误处理逻辑:

设置请求拦截器

// 添加请求拦截器
axios.interceptors.request.use(config => {
    // 在发送请求之前做些什么
    console.log('请求发送前:', config);
    return config;
}, error => {
    // 对请求错误做些什么
    return Promise.reject(error);
});

解释一下代码:

  • axios.interceptors.request.use() : 这是 axios 提供的一个方法,用于注册一个请求拦截器。请求拦截器会在每个请求发送之前被调用。

  • config => { ... } :

    • 这是一个回调函数,它接收一个 config 对象作为参数。config 对象包含了当前请求的所有配置信息,例如 URL、请求方法、请求头、请求体等。
    • 在这个回调函数中,你可以在请求发送之前对 config 进行修改或添加额外的逻辑。例如,你可以在这里添加认证头、记录请求时间、或者对请求数据进行加密。
    • 最后,必须返回 config 对象,以便 axios 可以继续执行请求。如果你返回的是一个修改后的 config,那么 axios 将使用这个修改后的配置来发起请求。
  • error => { ... } :

    • 这是另一个回调函数,用于处理请求拦截器中的错误。如果在请求拦截器中发生了错误(例如,配置无效或网络问题),这个回调函数会被调用。
    • 在这个例子中,我们使用 Promise.reject(error) 来拒绝这个请求,并将错误传递给后续的 .catch() 处理程序。这样可以确保请求不会继续执行,并且错误会被捕获。

【注意:注册响应拦截器就把request修改成response,可以实现响应后JSON解析等】

XMLHttpRequest 与 axios 的对比

为了更好地理解 XMLHttpRequestaxios 的差异,我们可以从多个角度进行对比。以下表格总结了两者的优缺点和适用场景:

特性XMLHttpRequest (XHR)axios
原生支持✅ 是(无需引入库)❌ 否(需要引入库)
浏览器兼容性✅ 广泛兼容(包括旧版浏览器)✅ 现代浏览器兼容(需 polyfill 支持旧版浏览器)
代码简洁性❌ 代码冗长,逻辑复杂✅ 代码简洁,易于维护
错误处理❌ 手动处理状态变化和错误,逻辑复杂✅ 内置 .catch() 方法,简化错误处理
Promise 支持❌ 不支持,需手动封装或使用第三方库✅ 内置 Promise 支持
JSON 解析❌ 需手动解析 JSON✅ 自动解析 JSON
取消请求❌ 需手动实现(如使用 abort()✅ 内置取消请求功能(CancelToken 或 AbortController
拦截器❌ 不支持✅ 支持请求和响应拦截器
跨域请求✅ 支持,但需手动处理✅ 内置支持,易于配置
社区支持✅ 广泛文档和社区支持,但学习曲线较陡峭✅ 活跃的开源社区,丰富的插件和扩展
性能✅ 原生对象,性能略优✅ 依赖库,但体积小,性能影响不大

如果觉得文章对您有所帮助的话,麻烦给小博主点点关注,点点赞咯😘,有问题欢迎各位小伙伴评论喔😊~