不能直接用 concat 合并 Promise 对象,必须先 await Promise.all() 或 Promise.allSettled() 等待所有请求完成再拼接;否则得到的是未解析的 Promise 数组,导致后续操作出错。

concat 不能直接合并 Promise 对象
直接把 fetch() 或 axios.get() 的返回值(即 Promise 实例)传给 Array.prototype.concat(),结果不会是你想要的数组,而是一堆未解析的 Promise。这是因为 concat() 只做浅拷贝和拼接,不等待异步完成。
常见错误现象:concat() 返回的数组里全是 Promise { ,后续调用 .map() 或 .filter() 会出错或返回 undefined。
- 必须先用
await Promise.all([...])或Promise.allSettled(...)等待所有请求完成 -
concat()是同步操作,只适合处理已 resolve 的数组 - 如果某个请求失败且你用的是
Promise.all(),整个合并流程会中断;需要容错时优先选Promise.allSettled()
正确做法:先 await 再 concat
典型场景是并发拉取多个 API(如分页列表、多模块数据),拿到响应体后再合并成一个扁平数组。
示例:合并两个用户列表接口的结果
const [usersA, usersB] = await Promise.all([
fetch('/api/users?page=1').then(r => r.json()),
fetch('/api/users?page=2').then(r => r.json())
]);
const allUsers = usersA.concat(usersB); // ✅ 此时 usersA 和 usersB 都是普通数组
- 不要写成
[promiseA, promiseB].concat()—— 这毫无意义 - 如果来源不止两个,可用展开运算符:
[...usersA, ...usersB, ...usersC],语义更清晰,性能也略优于concat() - 注意后端返回结构是否一致(比如都带
data字段),否则需统一提取:res.data || res
处理嵌套数组或非标准响应格式
有些接口返回的是 { code: 0, data: [...] } 结构,或者结果本身是二维数组(如每个请求返回一个子数组),这时直接 concat() 会得到嵌套结构。
- 若需扁平化:用
flat()(推荐)或reduce((acc, cur) => acc.concat(cur), []) - 若响应格式不统一,建议封装统一解析函数:
parseResponse(res) { return Array.isArray(res) ? res : res.data || [] } - 避免在
concat()前手动push(),易出错;优先用不可变方式组合
性能与错误边界提醒
并发请求数量大时(如 >10 个),Promise.all() 容易触发浏览器连接数限制或服务端限流,且单点失败即全盘失败。
- 对可靠性要求高时,改用
Promise.allSettled(),再过滤出status === 'fulfilled'的结果 - 大量请求建议加节流或分批(如每 5 个一组),避免阻塞主线程或超时
-
concat()本身无性能问题,但若数组极大(>10w 条),注意内存占用;必要时考虑流式处理或分页渲染
真正容易被忽略的是响应结构一致性——哪怕只是字段名大小写差异(userId vs user_id),也会让后续的 filter() 或 find() 失效。合并前务必校验或 normalize 数据结构。










