七、常见问题与解决方案
7.1 跨域问题(CORS)
问题:浏览器报错 No 'Access-Control-Allow-Origin' header is present
原因:浏览器的同源策略,前端和后端端口/域名不同时被阻止。
解决方案:
// 方案1:后端配置 CORS(推荐)
// Node.js + Express
const cors = require('cors');
app.use(cors({
origin: 'http://localhost:3000', // 允许的前端地址
credentials: true, // 允许携带 Cookie
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
// 方案2:开发时代理(Vite)
// vite.config.js
export default {
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
};
// 方案3:Nginx 反向代理
location /api/ {
proxy_pass http://backend-server:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
7.2 接口报 404
排查步骤:
检查 URL 是否正确
检查请求方法(GET/POST)是否匹配
检查服务器是否启动
检查路由是否注册
// 调试方法
console.log('请求URL:', url);
console.log('请求方法:', method);
// 在 Network 面板查看实际请求
// 查看 Request URL 是否拼写正确
7.3 接口报 401/403
401 Unauthorized:未认证(没有 token 或 token 过期)
403 Forbidden:已认证但无权限
// 处理 token 过期
instance.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
// 清除本地存储
localStorage.removeItem('token');
// 跳转到登录页
window.location.href = '/login';
// 可以尝试刷新 token
return refreshToken().then(() => {
return instance.request(error.config);
});
}
return Promise.reject(error);
}
);
7.4 数据格式不一致
// 问题:后端返回 camelCase,前端用 snake_case
// 后端:{ user_name: "张三" }
// 前端:data.userName → undefined
// 解决方案1:统一规范(推荐)
// 前后端约定都使用 camelCase
// 解决方案2:转换函数
function toCamelCase(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
if (Array.isArray(obj)) {
return obj.map(toCamelCase);
}
return Object.keys(obj).reduce((acc, key) => {
const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
acc[camelKey] = toCamelCase(obj[key]);
return acc;
}, {});
}
// 使用
const response = await fetch('/api/user');
const data = toCamelCase(await response.json());
7.5 重复请求问题
// 防抖(Debounce):输入框搜索
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
const searchUsers = debounce(async (keyword) => {
const result = await userApi.searchUsers(keyword);
setSearchResult(result);
}, 300);
// 节流(Throttle):滚动加载更多
function throttle(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
}
// 取消重复请求(使用 AbortController)
const abortController = new AbortController();
fetch('/api/search', { signal: abortController.signal });
// 发起新请求前取消上一个
if (currentRequest) {
currentRequest.abort();
}
currentRequest = new AbortController();
八、接口文档管理
8.1 文档必备内容
# 用户管理 API
## 基础信息
- Base URL: `https://api.example.com/v1`
- 认证方式: Bearer Token
- 请求格式: application/json
- 响应格式: application/json
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 40001 | 用户名不存在 |
| 40002 | 密码错误 |
| 40100 | token 过期 |
## 接口列表
### 获取用户信息
**接口**: `GET /users/{id}`
**路径参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | int | 是 | 用户ID |
**请求示例**:
GET /api/v1/users/123
Authorization: Bearer xxxxx
**响应示例**:
```json
{
"code": 200,
"data": {
"id": 123,
"name": "张三",
"email": "zhangsan@example.com"
}
}
### 8.2 自动化文档(Swagger UI)
```javascript
// 安装 swagger-jsdoc
npm install swagger-jsdoc swagger-ui-express
// swagger.js
const swaggerJsdoc = require('swagger-jsdoc');
const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'API 文档',
version: '1.0.0',
},
servers: [{ url: 'http://localhost:3000/api' }],
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
}
}
},
security: [{ bearerAuth: [] }]
},
apis: ['./routes/*.js']
};
module.exports = swaggerJsdoc(options);
// 使用
const swaggerUi = require('swagger-ui-express');
const swaggerSpec = require('./swagger');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
附:知识体系总结
API 接口与前后端联调
├── HTTP 协议
│ ├── 请求方法(GET、POST、PUT、DELETE、PATCH)
│ ├── 状态码(2xx、3xx、4xx、5xx)
│ └── Headers(Content-Type、Authorization)
├── RESTful 设计
│ ├── 资源命名(名词、复数、子资源)
│ ├── 统一响应格式
│ └── 错误处理
├── 前端联调
│ ├── 请求封装(拦截器、错误处理)
│ ├── 状态管理(loading、error、data)
│ └── Mock 数据
├── 调试工具
│ ├── Postman/Apifox
│ ├── 浏览器 DevTools
│ └── Swagger 文档
└── 常见问题
├── CORS 跨域
├── Token 管理
├── 重复请求
└── 超时重试