哈喽,各位奋战在 UI 和交互一线的伙伴们!
作为前端工程师,我们每天都在和 API 打交道。fetch
、axios
这些老朋友我们用得炉火纯青,信手拈来。我们向后端服务器发送请求,获取数据,然后把它们变成用户眼前的绚丽界面。
但是,你有没有想过:
- 如果我想自己快速搭一个 Mock Server 来伪造 API 数据,该怎么做?
- 如果我想在构建过程中,用脚本去拉取一些数据生成静态页面(比如 Next.js 或 Gatsby)呢?
- 如果我想解决烦人的跨域(CORS)问题,能不能自己搭一个中间层服务器来代理请求?
这些问题的答案,都指向了一个我们既熟悉又陌生的朋友 ------ Node.js。
别担心,它说的还是我们最爱的 JavaScript。今天,我就带你从前端的视角,轻松掌握如何在 Node.js 环境中接收请求 (当一个服务器)和发起请求(当一个客户端)。
💡 核心差异:浏览器 JS vs. Node.js JS
在我们开始之前,最重要的一点是理解环境差异:
- 浏览器环境 :有
window
、document
、location
等 DOM/BOM API。我们的代码运行在用户的浏览器沙箱里,出于安全考虑,有很多限制(比如跨域、文件系统访问受限)。 - Node.js 环境 :一个服务端的 JavaScript 运行环境。这里没有
window
,你不能alert('Hello')
。但你获得了更强大的能力:直接操作文件系统 (fs
)、处理网络请求 (http
)、与数据库交互等等。它让你的 JavaScript 走出了浏览器,拥有了整个服务器的控制权。
好了,心态调整完毕,我们开始动手!
📥 Part 1: 接收请求 ------ 变身 API 服务器
我们先来学习如何创建一个简单的服务器来接收来自浏览器或其它服务的请求。这对于搭建 Mock Server 简直是神器。
1.1 "原生"的 http
模块(了解即可)
Node.js 内置了一个 http
模块,可以让你用几行代码就创建一个 Web 服务器。我们来看看最原始的样子:
javascript
// server-native.js
const http = require('http'); // 1. 引入 http 模块
const server = http.createServer((req, res) => {
// 2. 创建服务器,并传入一个回调函数
// req (request): 包含所有请求信息,比如 URL、请求头、方法等
// res (response): 用于向客户端发送响应
console.log('收到一个请求!路径是:', req.url);
// 设置响应头
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
// 准备响应数据
const data = {
message: '你好,来自 Node.js 服务器的响应!',
};
// 发送响应体并结束响应
res.end(JSON.stringify(data));
});
const PORT = 3000; // 3. 定义端口号
server.listen(PORT, () => {
// 4. 启动服务器并监听端口
console.log(`🚀 服务器正在 http://localhost:${PORT} 上运行...`);
});
怎么运行?
- 确保你已经安装了 Node.js。
- 将以上代码保存为
server-native.js
。 - 在终端里运行:
node server-native.js
- 打开浏览器,访问
http://localhost:3000
,你就能看到返回的 JSON 数据了!
是不是感觉有点繁琐?要手动设置 writeHead
,还要 JSON.stringify
。没错,所以社区为我们提供了更优雅的解决方案。
1.2 使用 Express.js ------ 现代 Node.js Web 开发的标配
Express
是 Node.js 最流行、最简单的 Web 框架。你可以把它想象成后端的 "jQuery" 或 "React",它极大地简化了服务器的开发。
第一步:安装 Express
bash
# 新建一个项目文件夹并进入
mkdir node-request-demo
cd node-request-demo
# 初始化项目,生成 package.json
npm init -y
# 安装 express
npm install express
第二步:用 Express 重写服务器
javascript
// server-express.js
const express = require('express');
const app = express(); // 创建一个 Express 应用实例
const PORT = 3000;
// 中间件,用于解析请求体中的 JSON 数据
app.use(express.json());
// 路由:当客户端以 GET 方法请求根路径'/'时
app.get('/', (req, res) => {
// req 和 res 对象被 Express 封装得更好用
res.send('<h1>欢迎来到我的 Express 服务器!</h1>');
});
// 路由:当客户端以 GET 方法请求'/api/user'时
app.get('/api/user', (req, res) => {
const user = { id: 1, name: '前端小明', role: 'developer' };
// res.json() 会自动设置 Content-Type 并转换对象为 JSON
res.json(user);
});
// 路由:处理带参数的请求,比如 /api/user/123
app.get('/api/user/:id', (req, res) => {
const userId = req.params.id; // 获取 URL 中的参数
res.json({ id: userId, message: `正在查询 ID 为 ${userId} 的用户` });
});
// 路由:处理 POST 请求,比如用户登录
app.post('/api/login', (req, res) => {
const { username, password } = req.body; // 获取 POST 请求的 body 数据
console.log(`收到登录请求,用户名: ${username}, 密码: ${password}`);
if (username === 'admin' && password === '123456') {
res.json({ success: true, message: '登录成功!' });
} else {
res.status(401).json({ success: false, message: '用户名或密码错误' });
}
});
app.listen(PORT, () => {
console.log(`🚀 Express 服务器正在 http://localhost:${PORT} 上运行...`);
});
看到了吗?使用 Express 后,代码变得极其直观:
app.get()
、app.post()
直接对应 HTTP 方法,清晰地定义了路由。res.send()
可以发送各种类型的内容。res.json()
是我们前端的最爱,直接发送 JSON,无需任何额外操作。req.params
用于获取/:id
这样的 URL 参数。req.body
用于获取 POST/PUT 请求体中的数据(需要app.use(express.json())
中间件配合)。
现在,你可以用 Postman 或浏览器来测试 /
、/api/user
、/api/user/42
和 /api/login
这些不同的接口了。一个功能强大的 Mock Server 就这样轻松搞定!
📤 Part 2: 发起请求 ------ Node.js 访问外部 API
现在我们角色互换,让我们的 Node.js 程序作为客户端,去请求别的 API。这个技能在写构建脚本、数据处理、或者做 BFF(Backend for Frontend)层时非常有用。
2.1 官方推荐:内置的 fetch
API (Node.js v18+)
好消息!从 Node.js v18 开始,我们前端工程师最熟悉的 fetch
API 已经作为实验性特性被内置了(在 v21+ 中已稳定)。它的用法和浏览器中几乎一模一样!
javascript
// client-fetch.js
async function fetchGitHubUser(username) {
try {
const url = `https://api.github.com/users/${username}`;
console.log(`正在请求: ${url}`);
const response = await fetch(url); // 和浏览器里的 fetch 一样!
if (!response.ok) {
// response.ok 检查状态码是否在 200-299 范围内
throw new Error(`HTTP 错误! 状态码: ${response.status}`);
}
const data = await response.json(); // .json() 方法也完全一样
console.log('✅ 请求成功!');
console.log(`用户名: ${data.name}`);
console.log(`公司: ${data.company}`);
console.log(`粉丝数: ${data.followers}`);
} catch (error) {
console.error('❌ 请求失败:', error.message);
}
}
// 调用函数,发起请求
fetchGitHubUser('torvalds'); // 试试看 Linus Torvalds 的信息
在终端运行 node client-fetch.js
,你会看到它成功地从 GitHub API 拉取并打印了数据。对于前端来说,这是最平滑的过渡,几乎没有学习成本。
2.2 经典选择:axios
在 fetch
成为 Node.js 稳定功能之前,axios
是社区的首选。它是一个基于 Promise 的 HTTP 客户端,在浏览器和 Node.js 中都能使用。很多前端项目已经在使用它了,所以你可能对它也很熟悉。
第一步:安装 axios
bash
npm install axios
第二步:使用 axios 发起请求
javascript
// client-axios.js
const axios = require('axios');
async function fetchGitHubUserWithAxios(username) {
try {
const url = `https://api.github.com/users/${username}`;
console.log(`正在用 Axios 请求: ${url}`);
// Axios 的 GET 请求
const response = await axios.get(url);
// Axios 会在非 2xx 状态码时自动抛出异常,无需手动检查 response.ok
const data = response.data; // 响应数据直接在 .data 属性里
console.log('✅ 请求成功!');
console.log(`用户名: ${data.name}`);
console.log(`公司: ${data.company}`);
console.log(`粉丝数: ${data.followers}`);
} catch (error) {
// 错误处理更方便
if (error.response) {
// 请求已发出,但服务器返回了非 2xx 状态码
console.error(`❌ 请求失败,状态码: ${error.response.status}`);
console.error(error.response.data);
} else if (error.request) {
// 请求已发出,但没有收到响应
console.error('❌ 请求已发出但无响应:', error.request);
} else {
// 设置请求时发生了一些事情,触发了错误
console.error('❌ 请求设置错误:', error.message);
}
}
}
fetchGitHubUserWithAxios('yyx990803'); // 试试看尤雨溪的信息
axios
的优点:
- 同构性:一套代码,浏览器和 Node.js 通用。
- 自动转换:自动将响应数据转换为 JSON。
- 错误处理 :对 HTTP 错误(如 404, 500)直接抛出异常,方便
try...catch
捕获。 - 拦截器:可以设置请求和响应拦截器,统一处理如添加 token、记录日志等逻辑。
🔥 实战合体:创建一个解决跨域的代理服务器
现在我们把学到的知识结合起来。假设前端页面 (localhost:8080
) 想请求一个有跨域限制的第三方 API https://some-external-api.com/data
。我们可以创建一个 Node.js 服务器 (localhost:3000
) 作为代理。
流程: 前端页面
-> 我们的Node代理服务器
-> 第三方API
javascript
// proxy-server.js
const express = require('express');
const axios = require('axios'); // 或者用 fetch
const cors = require('cors'); // 引入 cors 中间件解决跨域问题
const app = express();
const PORT = 3000;
// 使用 cors 中间件,允许所有来源的跨域请求
app.use(cors());
app.get('/api/proxy', async (req, res) => {
try {
const externalApiUrl = 'https://api.quotable.io/random'; // 示例(该api已失效)
console.log('收到代理请求,正在转发至:', externalApiUrl);
// 我们的服务器去请求外部 API
const response = await axios.get(externalApiUrl);
// 将从外部 API 获取到的数据,原封不动地返回给前端
res.json(response.data);
console.log('✅ 代理成功!');
} catch (error) {
console.error('❌ 代理请求失败:', error.message);
res.status(500).json({ error: '代理服务器发生错误' });
}
});
app.listen(PORT, () => {
console.log(`🚀 代理服务器正在 http://localhost:${PORT} 上运行...`);
console.log('现在,你的前端可以请求 http://localhost:3000/api/proxy 来获取数据了!');
});
运行这个代理服务器:
- 安装
cors
:npm install cors
- 运行
node proxy-server.js
- 现在,在你的前端项目里,你就可以直接
fetch('http://localhost:3000/api/proxy')
,而不会遇到任何跨域问题了!
总结
恭喜你!你已经掌握了 Node.js 中最核心的网络能力:
- 接收请求 :使用 Express.js 可以快速、优雅地创建 API 服务器,处理 GET/POST 请求,解析 URL 参数和请求体。这是搭建 Mock Server 和完整后端应用的基础。
- 发起请求 :使用 内置
fetch
(Node.js v18+) 或 axios
,你的 Node.js 程序可以像在浏览器里一样,轻松地与任何外部 API 进行交互。
对于我们前端开发者来说,Node.js 不再是一个遥远而神秘的后端技术。它是我们工具箱的自然延伸,能帮我们解决开发中的实际问题,提升开发效率,甚至开启通往全栈工程师的大门。
希望这篇指南能为你点亮 Node.js 的技能树。现在,去动手试试吧!
Happy Coding! 😉