从零实现一个待办事项应用:前端必学的Ajax与Node.js实战

告别理论,手把手带你打通前后端交互的任督二脉

写在前面

作为一名前端开发者,我们每天都和Ajax打交道。但你真的理解它的工作原理吗?今天,我将带你从零开始,用原生JavaScript + Node.js实现一个完整的待办事项应用,彻底搞懂前后端交互的每一个环节。

一、为什么需要Ajax?

传统的网页交互是这样的:用户点击链接 → 浏览器向服务器请求完整页面 → 服务器返回新页面 → 页面刷新。这种体验有多糟糕,相信大家都深有体会。

Ajax(Asynchronous JavaScript and XML)的出现彻底改变了这一局面。它让我们可以在不刷新页面的情况下,向服务器请求数据并更新部分页面内容。

核心原理图解

text

markdown 复制代码
用户操作 → JavaScript发起请求 → 服务器处理 
                                    ↓
页面无刷新更新 ← 回调函数处理响应 ← 返回数据

二、数据交换的桥梁:JSON

在网络传输中,我们需要一种通用格式来传递数据。JSON(JavaScript Object Notation)就是这个标准。

JSON.stringify() 详解

javascript

javascript 复制代码
// 基本用法
const todo = { id: 1, title: '学习Ajax', completed: false };
const jsonStr = JSON.stringify(todo);
// 输出: '{"id":1,"title":"学习Ajax","completed":false}'

// 带格式化参数的用法
const prettyJson = JSON.stringify(todo, null, 2);
// 输出:
// {
//   "id": 1,
//   "title": "学习Ajax",
//   "completed": false
// }

参数说明:

  • value:要转换的对象
  • replacer:过滤函数,null表示不过滤
  • space:缩进空格数,提升可读性(团队规范必备)

三、服务端搭建:Node.js + HTTP模块

CommonJS模块化系统

早期的JavaScript没有模块化概念,Node.js通过require + module.exports实现了CommonJS规范。

javascript

javascript 复制代码
// 引入Node内置的http模块
const http = require('http');

// 待办数据
const todos = [
  { id: 1, title: '学习服务器端', completed: false },
  { id: 2, title: '学习ES6', completed: false },
  { id: 3, title: '掌握Ajax', completed: false }
];

// 创建HTTP服务器
const server = http.createServer((req, res) => {
  // 根据请求路径返回不同内容
  if (req.url === '/') {
    res.end('hello world');
  }
  
  if (req.url === '/todos') {
    // 解决跨域问题
    res.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应头:告诉浏览器返回的是JSON格式
    res.setHeader('Content-Type', 'application/json;charset=utf-8');
    // 将对象转为字符串并返回
    res.end(JSON.stringify(todos));
  }
});

// 监听3000端口
server.listen(3000, () => {
  console.log('Server is running on 3000 port');
});

关键技术点

知识点 说明
req.url 获取客户端请求的URL路径
res.setHeader() 设置响应头,解决跨域和内容类型问题
res.end() 返回响应,底层传输的是二进制数据
listen(port) 监听指定端口

四、前端请求:从XHR到Fetch

XMLHttpRequest 原生实现

这是Ajax最原始的实现方式,虽然代码稍显繁琐,但理解它是掌握所有异步请求的基础。

html

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>待办事项应用</title>
</head>
<body>
  <ul id="todos"></ul>
  <button id="btn">获取待办列表</button>

  <script>
    // 获取DOM元素
    const btn = document.getElementById('btn');
    const todosList = document.getElementById('todos');

    // 事件监听
    btn.addEventListener('click', function() {
      // 1. 创建XHR对象
      const xhr = new XMLHttpRequest();
      
      // 2. 打开HTTP通道(异步请求)
      xhr.open('GET', 'http://localhost:3000/todos', true);
      
      // 3. 监听响应状态变化
      xhr.onreadystatechange = function() {
        console.log('当前readyState:', xhr.readyState);
        
        // readyState === 4 表示请求完成
        // status === 200 表示成功
        if (xhr.readyState === 4 && xhr.status === 200) {
          // 将JSON字符串解析为对象
          const todos = JSON.parse(xhr.responseText);
          
          // 动态渲染页面
          todosList.innerHTML = todos
            .map(todo => `<li>${todo.title}</li>`)
            .join('');
        }
      };
      
      // 4. 发送请求
      xhr.send();
    });
    
    console.log('end'); // 验证异步特性
  </script>
</body>
</html>

XHR的readyState状态码

状态值 含义
0 未初始化,尚未调用open()
1 已打开,已调用open()
2 已发送,已调用send()
3 接收中,正在下载响应体
4 完成,响应已就绪

Fetch API(现代替代方案)

javascript

javascript 复制代码
// 更简洁的Fetch写法
fetch('http://localhost:3000/todos')
  .then(res => res.json())      // 解析JSON
  .then(data => console.log(data));  // 处理数据

五、JavaScript异步编程进阶

JavaScript是单线程语言,异步任务需要放在事件循环(Event Loop)中执行。

三种异步处理方式对比

javascript

javascript 复制代码
// 方式一:回调函数(XHR就是这种)
xhr.onreadystatechange = function() {
  // 回调地狱的雏形
};

// 方式二:Promise + then()
fetch(url)
  .then(res => res.json())
  .then(data => handleData(data))
  .catch(err => console.error(err));

// 方式三:async/await(最推荐)
async function getTodos() {
  try {
    const res = await fetch('http://localhost:3000/todos');
    const data = await res.json();
    console.log(data);
  } catch (error) {
    console.error('请求失败:', error);
  }
}

为什么async/await最优?

  1. 语法同步化:代码看起来像同步执行,实际是异步
  2. 错误处理统一:使用try/catch捕获所有错误
  3. 避免嵌套地狱:不再有.then链式调用的冗长代码

六、运行你的第一个全栈应用

启动步骤

bash

bash 复制代码
# 1. 启动Node服务器
node index.js
# 输出: Server is running on 3000 port

# 2. 用浏览器打开index.html
# 3. 点击按钮,查看效果

常见问题排查

问题 解决方案
跨域错误 服务端设置Access-Control-Allow-Origin: *
中文乱码 响应头添加charset=utf-8
数据无法显示 确认JSON.parse()是否正确

写在最后

今天我们完成了一个完整的前后端交互应用,涉及的知识点包括:

  • ✅ Ajax核心原理与XHR实现
  • ✅ JSON数据序列化与解析
  • ✅ Node.js HTTP模块搭建服务
  • ✅ CommonJS模块化规范
  • ✅ 异步编程的三种方式对比

这些知识构成了前端开发的基石,无论你使用React、Vue还是其他框架,底层原理都是相通的。

思考题: 如果我想添加"新增待办"的功能,前后端代码需要怎么修改?欢迎在评论区交流讨论!


如果觉得文章对你有帮助,欢迎点赞、收藏、关注三连支持一下~

相关推荐
yingyima1 小时前
JavaScript 正则表达式:从零开始的实战对比
前端
浩风祭月1 小时前
我用 AI 辅助重构了遗留项目的认证模块:从明文存储到 OAuth 2.0 的安全升级
后端·php·ai编程
用户34232323763171 小时前
数据质量与异常检测——当采集系统学会了“怀疑“
后端
Dilee2 小时前
Spring AI 核心链路拆解:ChatClient、Prompt、Advisor、ChatModel 到底怎么串起来?
后端
Sammyyyyy2 小时前
月之暗面 Kimi Code 0.4.0 发布,终端 AI 编码助手全面采用 TypeScript,实现毫秒级启动
前端·javascript·人工智能·ai·typescript·servbay
范什么特西2 小时前
配置文件xml和properties
xml·前端
jnene2 小时前
html 时间、价格筛选样式处理
前端·css·html
无风听海2 小时前
在 ASP.NET Core 开发环境中为自定义域名签发受信任的自签名证书—HSTS 启用后的完整实践
windows·后端·asp.net
无风听海2 小时前
深入理解 ASP.NET Core 中的UseHsts()
后端·asp.net