使用Promise.all重复调用同一接口时返回数据顺序异常问题
1. Promise.all的工作机制澄清
Promise.all不会按顺序执行Promise,它会同时启动所有传入的Promise任务(并行执行),但最终返回的结果数组是严格按照你传入的Promise数组的顺序排列的,和Promise实际完成的先后无关。比如你传入[getCall1(), getCall2(), getCall3()],then里的call1一定对应getCall1()的结果,call2对应getCall2()的结果,不管这三个请求谁先完成。
所以你日志里出现的结果顺序混乱(比如Run1输出2 1 3),不是Promise.all的顺序问题,而是getCall1()实际返回了2、getCall2()返回了1——也就是每个请求本身拿到的结果就不符合预期,甚至出现重复结果(Run3的1 1 2),这说明问题出在请求本身或者接口服务端。
2. 核心问题排查方向
(1)客户端请求参数的错误传递
看你的代码,调用internal_api.get时的参数写法存在问题:
internal_api.get(`get/users/`, data = {'name': 1})
这里的data = {'name': 1}是一个赋值表达式,而非传递请求参数的正确方式。如果data是未在当前函数作用域声明的变量,它会成为全局/外层作用域变量,三次调用getCall1/getCall2/getCall3时会依次覆盖data的值。由于Promise是异步启动的,三个请求几乎同时发送,最终可能所有请求都使用了最后一次赋值的data(或因执行时机不同拿到随机的data值),导致返回结果混乱。
正确的写法应该根据internal_api的参数规范传递数据,比如如果get方法的第二个参数是包含data字段的配置对象:
// 修正参数传递方式 internal_api.get(`get/users/`, { data: {'name': 1} })
(2)服务端并发请求的参数混淆
你提到调用不同接口时无此问题,仅调用同一接口时出现,这大概率是服务端的问题:
- 如果服务端处理请求时使用了全局变量/线程共享变量存储请求参数或查询条件,当多个并发请求过来时,后面的请求会覆盖前面的变量值,导致数据库查询使用了错误的参数,返回不符合预期的结果。
- 另外,接口执行大量数据库查询,处理时间较长,并发场景下更容易触发这种参数覆盖的问题。
(3)请求缓存问题
如果你的internal_api或浏览器对请求做了缓存,且缓存键只使用了接口路径(get/users/)而未包含请求参数(name),那么不同参数的请求会被当成同一个请求返回缓存结果,导致结果混乱或重复。
3. 验证与修复建议
- 先修正客户端的参数传递写法,确保每个请求的参数独立且正确传递,再测试是否仍出现结果混乱的情况。
- 如果客户端无问题,检查服务端代码:确保处理请求时使用的是当前请求的上下文参数,而非全局/共享变量;对于数据库查询,保证每个请求的查询条件是独立的。
- 排查缓存机制:确认缓存键包含完整的请求参数,避免不同参数的请求被错误缓存。
内容的提问来源于stack exchange,提问作者1daioo123mmd

