从 XMLHttpRequest 到 JSON 模拟:打通前后端通信的任督二脉

shell 复制代码
#### 引言:Web 2.0 的繁荣基石

我们常说的 Web 2.0 时代,其核心标志是什么?

是你在刷微博时,点赞数瞬间变化而页面无需刷新;是你在购物车里修改数量时,总价实时计算的丝滑体验。

这一切的背后,都离不开 Ajax(Asynchronous JavaScript and XML) 技术。

正如我在笔记中反复提醒自己的: "底层本质是 JS 可以主动发动 HTTP 请求,当前页面还在,动态更新页面。" 这就是互联网繁荣的基石。

第一部分:Node.js 原生搭建服务器 ------ 自己造个"后厨"

既然要通信,首先得有一个接收请求的服务器。很多新手习惯直接上手 Express,但我建议先用 Node.js 原生的 http 模块跑通一遍,这能让你彻底理解"请求-响应"模型。

核心代码实现:

javascript

编辑

javascript 复制代码
1const http = require('http');
2
3http.createServer((req, res) => {
4    // 模拟数据
5    const todos = [
6        { id: 1, title: '过六级', completed: false },
7        { id: 2, title: '过节', completed: false }
8    ];
9
10    // 路由处理
11    if (req.url === '/') {
12        res.end('hello world');
13    }
14    
15    if (req.url === '/todos') {
16        // 1. 设置响应头,告诉浏览器这是 JSON 数据
17        res.setHeader('Content-Type', 'application/json; charset=utf-8');
18        // 2. 关键:必须将对象序列化为字符串才能传输
19        res.end(JSON.stringify(todos));
20    }
21
22}).listen(3000, () => {
23    console.log('Server is running at 3000 port');
24});

💡 踩坑指南:

  • res.setHeader 的正确写法 :注意,Content-Type 的值应该是一个字符串。我之前在笔记里写成了 res.setHeader('Content-Type','application/json','utf-8'),这是错误的!第三个参数会被忽略。正确的 MIME 类型写法是 'application/json; charset=utf-8'
  • 端口占用 :如果遇到 EADDRINUSE 错误,说明 3000 端口被占用了,记得用 netstattaskkill 清理。

第二部分:JSON ------ 数据传输的"标准集装箱"

服务器准备好了数据,但网络传输只认"字符串"或"二进制",不认识 JavaScript 对象。这时候,JSON.stringify() 就像一个打包机。

JSON.stringify 三参数详解:

表格

参数 作用 笔记心得
value 必填。要序列化的对象/数组。 将 JS 对象转为 JSON 字符串,便于网络传输。
replacer 可选。过滤字段。 类似"白名单"或"安检员"。传 null 则原样序列化。
space 可选。格式化空格。 团队开发规范利器。传 24 增加可读性,方便调试。

代码示例:

javascript

编辑

javascript 复制代码
1// 增加可读性,方便在控制台查看结构
2console.log(JSON.stringify(todos, null, 2));

第三部分:XMLHttpRequest ------ Fetch 的"祖师爷"

现在大家都用 fetch,但 XMLHttpRequest (XHR) 是这一切的前辈。理解它,你才能真正明白 fetch 封装了什么。

原生 XHR 的"五步法":

  1. 实例化const xhr = new XMLHttpRequest();
  2. 配置xhr.open('GET', url, true); (true 代表异步)
  3. 监听xhr.onreadystatechange (核心:监听状态变化)
  4. 发送xhr.send();
  5. 处理:在回调中解析数据并更新 DOM。

实战代码:

javascript

编辑

ini 复制代码
1const xhr = new XMLHttpRequest();
2xhr.open('GET', 'http://localhost:3000/todos', true);
3
4// 这里的逻辑非常关键
5xhr.onreadystatechange = function() {
6    // readyState === 4 代表数据接收完毕
7    if (xhr.readyState === 4) {
8        // 1. 拿到的是字符串,必须 JSON.parse 转回对象
9        const todos = JSON.parse(xhr.responseText);
10        
11        // 2. 动态更新页面 (Map + 模板字符串)
12        document.getElementById('todos').innerHTML = todos
13            .map(item => `<li>${item.title}</li>`)
14            .join(''); // 记得 join('') 去除逗号
15    }
16};
17
18xhr.send();

🧠 核心原理:Event Loop

JS 是单线程的。当 xhr.send() 发出请求后,JS 并不会卡住等待数据,而是继续执行后面的代码(比如 console.log('end'))。这就是异步。当数据回来时,回调函数会被放入 Event Loop 队列,等待执行。

第四部分:没有接口怎么开发?------ 前端 Mock 艺术

在实际工作中,后端接口往往滞后。这时候,我们不能干等。根据我的经验,有两种最高效的 Mock 方式:

  1. 本地 JSON 文件 (最简单):
    直接创建 mock.json,用 fetch('./mock.json') 请求。适合静态数据展示。
  2. Node.js 中间层 (进阶):
    像上面那样写一个简单的 Node 服务,拦截请求并返回模拟数据。这能完美模拟 POST/DELETE 等增删改操作。

结语

XMLHttpRequest 的回调地狱,到 Promise 的链式调用,再到如今 async/await 的同步写法,前端异步处理的演进史,就是一部为了代码更优雅、更易维护的奋斗史。

希望这篇文章能帮你打通前后端通信的任督二脉。记住,框架只是语法糖,底层原理才是永恒的财富。

相关推荐
weixin_471383031 小时前
Taro-03-页面生命周期
前端·javascript·taro
Asize1 小时前
数组数据结构底层:从灵活到陷阱
前端·javascript·算法
十九画生1 小时前
Ajax 入门:用 XHR 理解前后端异步请求
前端·javascript·后端
源图客3 小时前
境外电商 - 龙虾智能体-综合选品推荐报告
开发语言·javascript·ecmascript
磊 子3 小时前
C++设计模式
javascript·c++·设计模式
智码看视界4 小时前
老梁聊全栈:JavaScript 原型链深入探索对象继承的奥秘
前端·javascript·ecmascript
智码看视界4 小时前
老梁聊全栈系列 JavaScript语言本质:从原型链到异步编程的深度解析
开发语言·javascript·全栈·javascript核心
触底反弹5 小时前
一文彻底搞懂 JavaScript 栈和队列(建议收藏)
javascript·算法·面试
Asize5 小时前
Prompt 驱动 NLP:从 ES6 模块化到文本推理实战
javascript·人工智能·机器学习