共计 1716 个字符,预计需要花费 5 分钟才能阅读完成。
记得刚入行时,我遇到过这样一个 Bug:前端传递的数组参数直接拼接到 URL 上,导致后端接口爆出 500 错误。当时排查了半天才发现,原来未序列化的数组参数在 GET 请求中变成了?ids=1,2,3,而后端期望的是标准查询字符串格式?ids[]=1&ids[]=2。这个教训让我意识到,正确处理 List 参数绝非小事。

一、List 参数处理的核心方案
1. JSON 序列化 vs FormData
- JSON.stringify 方案(适合复杂数据结构)
// 适用于 POST/PUT 请求体 const payload = {items: JSON.stringify([{id: 1}, {id: 2}]) }; - 优点:保持数据结构完整,支持嵌套对象
-
缺点:需要手动处理反序列化,URL 长度受限
-
URLSearchParams 方案(适合简单列表)
// 适用于 GET 请求或 x -www-form-urlencoded const params = new URLSearchParams(); ['a', 'b'].forEach(v => params.append('chars', v)); - 优点:自动处理 URL 编码,符合标准表单格式
- 缺点:不支持复杂对象结构
2. 带完整错误处理的代码模板
Axios 实现(含类型声明)
/**
* 分页获取商品列表
* @param ids 商品 ID 数组
* @param page 当前页码
*/
async function fetchProducts(ids: string[],
page = 1
): Promise<Product[]> {
try {const { data} = await axios.post('/api/products', {ids: JSON.stringify(ids),
page
}, {
headers: {'Content-Type': 'application/json'},
timeout: 5000
});
return data;
} catch (err) {if (axios.isAxiosError(err)) {console.error(` 请求失败: ${err.response?.status || err.code}`);
}
throw new Error('获取商品列表失败');
}
}
Fetch API 实现
// 使用 FormData 处理文件 + 列表混合上传
const formData = new FormData();
files.forEach(file => formData.append('attachments', file));
params.forEach((value, key) => formData.append(key, value));
// 添加请求中断能力
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
fetch('/api/upload', {
method: 'POST',
body: formData,
signal: controller.signal
}).then(handleResponse);
二、生产环境避坑指南
1. 特殊字符编码
- 使用
encodeURIComponent处理单个值 - 避免手动拼接 URL,优先使用
URLSearchParams
2. 大数组分块传输
// 每 100 条数据分一个批次
const chunkSize = 100;
for (let i = 0; i < bigArray.length; i += chunkSize) {const chunk = bigArray.slice(i, i + chunkSize);
await processBatch(chunk);
}
3. 内存泄漏预防
- 及时清理未完成的请求(AbortController)
- 避免在闭包中保留大数组引用
- 使用 WeakMap 替代 Map 存储临时数据
三、实战示例与思考
查看完整示例代码(模拟链接)
课后思考题
- 当 API 需要新增参数时,如何保证旧版本客户端兼容?
- 遇到 413 请求体过大错误,有哪些降级处理方案?
在实际项目中,我发现合理处理 List 参数不仅能提升接口性能,还能显著降低联调成本。建议大家在设计接口时,明确约定数组参数的传递规范,并在前端封装统一的参数处理工具函数。
正文完
发表至: 前端开发
近一天内
