大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
Node.js
这一课你将能做到
- 用 Node.js 写第一个 HTTP 服务器
- 用 Express 框架写 RESTful API
- 连接数据库并返回 JSON 数据
为什么要学
JavaScript 以前只能跑在浏览器里,操作 DOM、响应点击。Node.js 让 JavaScript 能跑在服务器上,写后端 API、操作文件、连接数据库。前后端都用 JS,技术栈统一。
人话:Node.js 是「翻译官」,让 JavaScript 能跟操作系统、数据库打交道。
先建立图像
// 浏览器里的 JS:操作 DOM
document.querySelector('#btn').addEventListener('click', () => {
alert(' clicked');
});
// Node.js 里的 JS:操作服务器
const http = require('http');
http.createServer((req, res) => {
res.end('Hello from server');
}).listen(3000);
运行后:
浏览器访问 http://localhost:3000
→ 显示 "Hello from server"
跟着做
步骤 1:第一个 HTTP 服务器
// server.js
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('你好,Node.js!');
});
server.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});
node server.js
步骤 2:路由处理
const http = require('http');
const url = require('url');
const server = http.createServer((req, res) => {
const { pathname, query } = url.parse(req.url, true);
if (pathname === '/api/courses') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify([
{ id: 1, title: 'HTML' },
{ id: 2, title: 'CSS' }
]));
} else if (pathname === '/api/user') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ name: query.name || '访客' }));
} else {
res.writeHead(404);
res.end('Not Found');
}
});
server.listen(3000);
步骤 3:Express 框架(推荐)
原生 http 模块太啰嗦,Express 封装了常用功能。
npm init -y
npm install express
// app.js
const express = require('express');
const app = express();
// 中间件:解析 JSON 请求体
app.use(express.json());
// GET 请求
app.get('/api/courses', (req, res) => {
res.json([
{ id: 1, title: 'HTML' },
{ id: 2, title: 'CSS' }
]);
});
// POST 请求
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
if (username === 'admin' && password === '123456') {
res.json({ code: 0, data: { token: 'abc123' } });
} else {
res.json({ code: 1, msg: '用户名或密码错误' });
}
});
// 启动
app.listen(3000, () => {
console.log('Express 服务器运行在 http://localhost:3000');
});
步骤 4:连接 MySQL 数据库
npm install mysql2
const mysql = require('mysql2/promise');
// 创建连接池
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '123456',
database: 'codeforge'
});
// 查询课程列表
app.get('/api/courses', async (req, res) => {
try {
const [rows] = await pool.query('SELECT * FROM course');
res.json({ code: 0, data: rows });
} catch (err) {
console.error('数据库错误:', err);
res.status(500).json({ code: 500, msg: '服务器内部错误' });
}
});
步骤 5:中间件与错误处理
// 日志中间件
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next(); // 传给下一个中间件
});
// 404 处理
app.use((req, res) => {
res.status(404).json({ code: 404, msg: '接口不存在' });
});
// 错误处理(四个参数)
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ code: 500, msg: '服务器错误' });
});
步骤 6:环境变量与配置
npm install dotenv
// .env
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
PORT=3000
require('dotenv').config();
const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: 'codeforge'
});
app.listen(process.env.PORT || 3000);
讲清楚要点
- Node.js 是运行时:让 JavaScript 跑在服务器上,不是框架。
- Express 是框架:封装了路由、中间件、请求响应处理,简化开发。
- 异步非阻塞:Node.js 用事件循环处理并发,适合 I/O 密集型(API、文件读写)。
- npm 是包管理器:安装第三方库(express、mysql2、dotenv)。
- CommonJS 模块:
require导入,module.exports导出。
你可能会懵的地方
-
Node.js 和浏览器 JS 有什么区别? 浏览器 JS 有 DOM、BOM(window、document);Node.js 有 fs、http、path 等系统模块,没有 DOM。
-
Express 和 Koa 选哪个? Express 生态成熟、中间件多;Koa 更轻量、用 async/await。中小项目 Express 足够。
-
为什么用连接池而不是单个连接? 连接池复用连接,避免频繁创建销毁,提升性能。
-
回调地狱怎么办? 用
async/await或 Promise 链,避免嵌套回调。 -
Node.js 适合 CPU 密集型吗? 不适合。Node.js 单线程,CPU 密集型会阻塞事件循环。适合 I/O 密集型(API、文件、数据库)。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
res.send() 后忘记 return | 继续执行后续代码 | return res.send(...) |
回调里用 this 指代 server | 指向丢失 | 用箭头函数或 .bind(this) |
| 同步方法阻塞事件循环 | fs.readFileSync 卡住所有请求 | 用异步 fs.readFile 或 await |
| 密码明文存数据库 | 安全隐患 | 用 bcrypt 哈希 |
| 不处理 Promise 异常 | 未捕获的 rejection 崩溃 | 用 try/catch 或 .catch() |
卡点急救
- 端口被占用:
Error: listen EADDRINUSE,换端口或杀掉占用进程(netstat -ano | findstr :3000)。 - 数据库连接失败:检查 MySQL 是否启动、用户名密码、防火墙。
- CORS 跨域报错:安装
cors中间件,app.use(cors())。
面试常问
-
事件循环(Event Loop)? 同步代码 → 微任务(Promise)→ 宏任务(setTimeout、setImmediate)。Node.js 还有
process.nextTick优先级最高。 -
中间件是什么? 请求到达路由前的处理函数,可链式调用。用于日志、鉴权、解析请求体。
-
CommonJS 和 ES Module 区别? CommonJS:
require/module.exports,同步加载,Node.js 默认;ES Module:import/export,异步加载,浏览器和现代 Node.js 支持。 -
如何防止 SQL 注入? 用参数化查询:
pool.query('SELECT * FROM user WHERE id = ?', [id]),不要拼接字符串。
自测三问
- Express 中
app.use()的作用? - 为什么数据库操作要用
async/await? - 环境变量文件
.env为什么要加到.gitignore?
小结一句话
Node.js 让 JavaScript 跑在服务器,Express 框架简化 API 开发,连接池管理数据库连接。
延伸
- Express 官方文档
- 下一课:PostgreSQL 关系型数据库。