搞懂了AJAX的三种实现方式 一起来尝试手写一个AJAX

前言

在现代的Web开发中,异步请求是不可或缺的一部分,而AJAX(Asynchronous JavaScript and XML)是实现异步请求的重要技术。在上篇文章中我们详细学习了实现AJAX的三种方法。今天为了更好地深入理解AJAX,我们将通过手写一个AJAX请求的过程,并使用Promise进行封装,使其中过程更真实且易于理解。那么话不多说,开启实战!

手写AJAX代码

在详细介绍之前,先来看我们今天的完整代码,接下来我会为大家逐步剖析这份代码然后进行详解。

完整代码

js 复制代码
function getDataByAjax(url) {
    return new Promise((resolve, reject) => {
        console.log('1111');
        // 浏览器的兼容性 ie 低版本不支持XMLHttpRequest
        const xhr = XMLHttpRequest
            ? new XMLHttpRequest()
            : new ActiveXObject('Microsoft.XMLHTTP')
        // 打开主动请求数据
        console.log(xhr.readyState); // 0
        xhr.open('GET', url, false)
        console.log(xhr.readyState); // 1 HTTP 请求通道打开
        xhr.onreadystatechange = function () {
            console.log(xhr.readyState); // 4 表示完成所有数据的传输
            if (xhr.readyState !== 4) reuturn
            if (xhr.status === 200 || xhr.status === 304) {
                resolve(xhr.responseText) // 4
            } else {
                reject(xhr.responseText)
            }
        }
        xhr.send()
        console.log(xhr.readyState);
    })
}

1. 异步请求概述

AJAX允许我们通过JavaScript向服务器发送请求并在不刷新整个页面的情况下获取或发送数据。这对于实现更流畅、动态的用户体验至关重要。

2. XMLHttpRequest对象

在JavaScript中,我们使用XMLHttpRequest对象来创建和发送AJAX请求。因为ie低版本不支持XMLHttpRequest,所以为了考虑兼容性,我们通过条件语句选择使用XMLHttpRequestActiveXObject

js 复制代码
const xhr = window.XMLHttpRequest
    ? new XMLHttpRequest()
    : new ActiveXObject('Microsoft.XMLHTTP');

封装为Promise

为了更好地处理异步操作,我们使用ES6中引入的Promise对象。因为其提供了一种更清晰的异步编程模式。

js 复制代码
function getDataByAjax(url) {
    return new Promise((resolve, reject) => {
        const xhr = window.XMLHttpRequest
            ? new XMLHttpRequest()
            : new ActiveXObject('Microsoft.XMLHTTP');
        xhr.open('GET', url, true);

        xhr.onreadystatechange = function () {
            if (xhr.readyState !== 4) return;
            if (xhr.status === 200 || xhr.status === 304) {
                resolve(xhr.responseText);
            } else {
                reject(xhr.responseText);
            }
        };
        xhr.send();
    });
}

解释:

  1. return new Promise((resolve, reject) => { ... }) getDataByAjax函数返回一个Promise对象,该Promise在异步操作完成时会调用resolvereject,需要注意的是Promise这个对象本身在事件循环机制中并不会被当作异步任务,而是以同步任务进行执行,当实例化Promise这个对象时,引擎会立即执行传给它的执行器(executor),它就相当于是可以存放异步任务的一个容器,所以我们会将发送请求-获取响应放在这个容器里面。

  2. const xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); 创建XMLHttpRequest对象,以便进行AJAX请求。通过这种方式实现了对不同浏览器的兼容性处理。

  3. xhr.open('GET', url, true); 配置AJAX请求,使用GET方法,指定请求的URL,并设置为异步执行。这时候如果我们打印xhr.readyState,结果会是1,表示HTTP请求通道已经打开。

  4. xhr.onreadystatechange = function () { ... } 监听xhr对象的onreadystatechange事件,当请求状态发生变化时触发。这时候我们再打印xhr.readyState,结果会是4,表示完成所有数据的传输。

  5. if (xhr.readyState !== 4) return;onreadystatechange事件中,首先检查请求状态是否为4,表示请求完成。

  6. if (xhr.status === 200 || xhr.status === 304) { ... } else { ... } 根据响应状态码判断请求的成功与失败。如果状态码为200304,表示成功,调用resolve并传递响应文本;否则,调用reject并传递响应文本。

  7. xhr.send(); 最后完成上述步骤,发送AJAX请求。

我们手写的AJAX函数到这里就完成了,这段函数通过使用Promise,使得该函数在其他地方调用时,也可以使用.then().catch()来处理AJAX等异步操作的成功和失败情况。

调用手写的AJAX函数

在上面我们已经完成手写AJAX的函数了,接下来让我们检验一下其是否真的可以拿到我们指定的URL中的数据呢?

完整代码

js 复制代码
// 使用立即执行函数表达式调用异步函数
(async function () {
    try {
        // 调用异步函数并获取返回的Promise对象
        const p = getDataByAjax('https://api.github.com/users/sAnL1ng/repos');
        // 输出信息
        console.log(p); // Promise 处于 pending 状态
        // 使用 await 等待异步操作完成
        const data = await p;
        
        // 异步操作完成后的处理
        console.log(p); // Promise 从 pending 到 fulfilled 状态
        console.log(JSON.parse(data));
    } catch (err) {
        console.error(err); // 捕获可能的错误
    }
})();

然后我们在谷歌浏览器的控制台中运行上述代码就拿到我们想要的数据结果啦(这里请求的数据是博主GitHub中的仓库内容):

代码解析

  1. 定义异步函数: 首先我们使用async function关键字定义了一个异步函数getDataByAjax,它返回一个Promise对象,用于处理AJAX请求。

  2. Promise状态的观察: 在第一个console.log(p);处,输出了Promise对象p的状态,此时处于pending状态,因为异步操作还没有完成。

  3. 使用 await 等待异步操作完成: 在第二个console.log(p);处,输出了Promise对象p的状态,此时p的状态已经从pending变为fulfilled,因为前面的await p等待了p的异步操作完成。

  4. 捕获可能的错误: 最后我们使用try...catch块捕获可能的错误,确保对异步操作中的异常情况进行处理。

总结

到这里,我们就完成了今天的全部内容啦~总的来说,手写AJAX首先我们将整个函数封装成一个Promise对象,然后使用XMLHttpRequest对象来创建和发送AJAX请求,最后根据响应状态码判断请求的成功与失败。

在当下的前端环境中不管是工作还是面试,AJAX都是一个十分重要的知识点,对此不太熟悉的小伙伴可以先看我上一篇介绍AJAX三种方法的基础篇,了解完后再来学习如何手写AJAX深入了解AJAX,希望本文对大家有所帮助,感谢阅读,我是散陵我们下篇文章再见!

结语

那么到了这里我们今天的文章就结束啦~

创作不易,如果感觉这个文章对你有帮助的话,点个赞吧♥

更多内容如何开启异步通信的新境界?搞懂AJAX中的这三招

ReacheMe : GitHub Gitee

相关推荐
Dragon Wu几秒前
前端 Canvas 绘画 总结
前端
CodeToGym5 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫6 分钟前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫10 分钟前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
Cwhat11 分钟前
前端性能优化2
前端
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
瑶琴AI前端1 小时前
uniapp组件实现省市区三级联动选择
java·前端·uni-app
会发光的猪。2 小时前
如何在vscode中安装git详细新手教程
前端·ide·git·vscode
别拿曾经看以后~3 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死3 小时前
导航栏及下拉菜单的实现
前端·css·css3