我是如何优雅地手写AJAX的

浅聊一下

提到AJAX,好像有点熟悉...


没错,在上一篇文章里,我们讲了如何使用AJAX来请求数据

搞懂 AJAX:写给前端新手的实用教程

在本篇文章中,我们将对其进行一个升华,带领大家来手写一个AJAX...

手写AJAX

先给大家展示代码,再来一步步讲解

js 复制代码
function getDataByAjax(url) {
            //promise 是 es6 提供的一个类,实例化的时候 立即执行传给他的执行器
            //executor new Promise同步执行
            return new Promise((resolve, reject) => {
                console.log('11111');
                //异步任务的容器
                // setTimeout(()=>{
                //     resolve('5555')
                // },2000)
                //浏览器的兼容性 IE 低版本不支持XMLHttpRequest
                const xhr = XMLHttpRequest
                    ? new XMLHttpRequest()
                    : new ActiveXObject('Microsoft.XMLHttp');
                // 主动请求数据 open:打开
                console.log(xhr.readyState);//0 表示 XHR 对象已经被创建,但尚未调用 open() 方法
                xhr.open('GET', url, false);
                console.log(xhr.readyState);//1 http请求通道打开
                xhr.onreadystatechange = function () {
                    console.log(xhr.readyState);//完成所有数据的传输
                    if (xhr.readyState !== 4) {
                        return;
                    }
                    //200成功 304 Not Modifyed 性能优化 服务器端资源 
                    // 在多次请求中并没有改变 (updata_time 文件没修改返回304) 304响应头 不传输响应体
                    // 前端拿到304怎么办? 前端会去浏览器缓存里拿之前的结果 协商缓存
                    if (xhr.status === 200 || xhr.status === 304) {
                        resolve(xhr.responseText)
                    } else {
                        reject(xhr.responseText)
                    }
                }
                xhr.send();
                console.log(xhr.readyState);
            })
        }

我们知道,获取数据是需要耗时的,所以我们所执行的方法是一个异步任务

要在等待请求完毕后继续执行任务,那我们就得用到Promise,同样的要是有掘友对于Promise不太熟悉,可以去看我之前的文章(Promise:解决JavaScript异步编程难题 - 掘金 (juejin.cn))

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

我们在上一篇文章中使用的只有XMLHttpRequest,为什么这里还需要用到三元运算符呢?

在这里,我们使用这种方法来提高浏览器的兼容性,在一些旧版本的IE浏览器中,没有全局的XMLHttpRequest对象, 则使用 new ActiveXObject('Microsoft.XMLHttp') 来创建一个 ActiveXObject 对象。

js 复制代码
xhr.onreadystatechange = function () {
                    console.log(xhr.readyState);//完成所有数据的传输
                    if (xhr.readyState !== 4) {
                        return;
                    }
                    //200成功 304 Not Modifyed 性能优化 服务器端资源 
                    // 在多次请求中并没有改变 (updata_time 文件没修改返回304) 304响应头 不传输响应体
                    // 前端拿到304怎么办? 前端会去浏览器缓存里拿之前的结果 协商缓存
                    if (xhr.status === 200 || xhr.status === 304) {
                        resolve(xhr.responseText)
                    } else {
                        reject(xhr.responseText)
                    }
                }

在if判断中,判断状态码如果不为4.则说明数据没有完成传输,直接return

当xhr.status === 200 时,说明此时请求成功,那么当他等于304又代表了什么呢?

304 代表多次获取数据时,数据并没有发生改变

那么当前端拿到304的时候该怎么办呢?

应该去找到之前的数据,前端会去浏览器缓存里拿之前的结果

响应成功,通过 resolve(xhr.responseText) 将响应文本传递给 Promise 的 resolve 函数。如果请求失败,通过 reject(xhr.responseText) 将响应文本传递给 Promise 的 reject 函数。

调用getDataByAjax()

接下来我们来调用getDataByAjax()

js 复制代码
(async function () {
            const p = getDataByAjax('https://api.github.com/users/shunwuyu/repos')

            console.log('2222');
            console.log(p);//panding 状态
            //await 后面是一个promise对象
            try {
                const data = await p//卡在这里
                console.log('3333');
                console.log(p);//fullfilled
                console.log(data);
            } catch (error) {
                console.log(err);
            }

        })()
  1. const p = getDataByAjax('https://api.github.com/users/shunwuyu/repos'):调用 getDataByAjax 函数,该函数返回一个 Promise 对象,代表异步操作。p 变量将包含这个 Promise。
  2. console.log('2222');:输出 '2222',这是在异步操作执行的过程中同步执行的代码。
  3. console.log(p);:输出 Promise 对象,此时 Promise 处于挂起(pending)状态,因为异步操作尚未完成。
  4. const data = await p:通过 await 关键字等待 p Promise 对象的解决。这会阻塞后续代码的执行,直到 Promise 状态变为已解决(fulfilled)或者拒绝(rejected)。
  5. console.log('3333');:当 Promise 对象解决后,输出 '3333'。
  6. console.log(p);:输出 Promise 对象,此时 Promise 处于已解决状态(fulfilled)。

我们来看结果:

结尾

今天手写的AJAX着实优雅,把他写给面试官,相信他会给你嘎嘎加分

相关推荐
尾善爱看海1 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
驳是2 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea2 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持2 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者2 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn3 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
计算机魔术师5 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端
计算机魔术师5 小时前
OpenAI的AI代理偷偷给RubyGems下毒,我们却毫无察觉
前端
甲维斯5 小时前
0代码,0建模,3句话开发一个3D游戏!
前端·游戏·游戏开发
IT_陈寒5 小时前
Vue的响应式更新把我坑惨了,原来问题出在这
前端·人工智能·后端