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 端口被占用了,记得用netstat或taskkill清理。
第二部分:JSON ------ 数据传输的"标准集装箱"
服务器准备好了数据,但网络传输只认"字符串"或"二进制",不认识 JavaScript 对象。这时候,JSON.stringify() 就像一个打包机。
JSON.stringify 三参数详解:
表格
| 参数 | 作用 | 笔记心得 |
|---|---|---|
| value | 必填。要序列化的对象/数组。 | 将 JS 对象转为 JSON 字符串,便于网络传输。 |
| replacer | 可选。过滤字段。 | 类似"白名单"或"安检员"。传 null 则原样序列化。 |
| space | 可选。格式化空格。 | 团队开发规范利器。传 2 或 4 增加可读性,方便调试。 |
代码示例:
javascript
编辑
javascript
1// 增加可读性,方便在控制台查看结构
2console.log(JSON.stringify(todos, null, 2));
第三部分:XMLHttpRequest ------ Fetch 的"祖师爷"
现在大家都用 fetch,但 XMLHttpRequest (XHR) 是这一切的前辈。理解它,你才能真正明白 fetch 封装了什么。
原生 XHR 的"五步法":
- 实例化 :
const xhr = new XMLHttpRequest(); - 配置 :
xhr.open('GET', url, true);(true 代表异步) - 监听 :
xhr.onreadystatechange(核心:监听状态变化) - 发送 :
xhr.send(); - 处理:在回调中解析数据并更新 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 方式:
- 本地 JSON 文件 (最简单):
直接创建mock.json,用fetch('./mock.json')请求。适合静态数据展示。 - Node.js 中间层 (进阶):
像上面那样写一个简单的 Node 服务,拦截请求并返回模拟数据。这能完美模拟 POST/DELETE 等增删改操作。
结语
从 XMLHttpRequest 的回调地狱,到 Promise 的链式调用,再到如今 async/await 的同步写法,前端异步处理的演进史,就是一部为了代码更优雅、更易维护的奋斗史。
希望这篇文章能帮你打通前后端通信的任督二脉。记住,框架只是语法糖,底层原理才是永恒的财富。