使用forEach遍历调用异步函数返回结果异常,如何解决?
问题分析与解决方案
咱们先拆解下为啥会出现不符合预期的输出:
- 定时器参数错误:你代码里的
setTimeout用了i作为延迟时间,但这个i根本没定义,相当于延迟时间是0,导致两个请求几乎同时发给服务器。服务器处理请求的顺序不一定和发送顺序一致,响应回来的结果自然就乱了,这才出现了1, 2和2, 1的情况。 - 服务器参数获取错误:原服务器代码里
req.num是错误的写法,GET请求的参数应该从req.query里取,不然根本拿不到你传的num值,这也会导致返回结果异常。 - forEach不支持异步顺序控制:forEach本身不会等待异步操作完成,就算加了定时器,也没法保证请求的执行顺序。
接下来给你两种解决思路,按需选择:
方案一:顺序执行请求(逐个发送,上一个完成再发下一个)
这种方式适合需要严格按顺序处理请求的场景,比如依赖前一个请求结果的情况:
// 修正后的异步请求函数 async function query(num) { // 假设request是类似axios的请求库,参数要放在params里传给后端 let data = await request(url, { params: { num } }); console.log(num, data); } // 用for...of替代forEach,保证异步操作顺序执行 async function processQueries() { const nums = [1, 2]; for (const num of nums) { await query(num); console.log(num); } } // 启动执行 processQueries(); // 修正后的服务器代码 server.get('*', function(req, res) { // 从query中正确获取num参数 let num = req.query.num; // 注意:res.send需要传字符串/Buffer等,转成字符串更稳妥 res.send(num.toString()); })
方案二:并行发送请求但按顺序输出结果
如果想同时发送请求提高效率,但又要保证输出顺序和请求顺序一致,可以用Promise.all:
async function query(num) { let data = await request(url, { params: { num } }); // 返回num和对应的data,方便后续按顺序处理 return { num, data }; } async function processQueries() { // 先创建所有请求的Promise const promises = [1, 2].map(num => query(num)); // 等待所有请求完成,结果会按原Promise数组的顺序返回 const results = await Promise.all(promises); // 按顺序输出结果 results.forEach(({ num, data }) => { console.log(num, data); console.log(num); }); } processQueries(); // 服务器代码同方案一的修正版 server.get('*', function(req, res) { let num = req.query.num; res.send(num.toString()); })
这样调整后,就能得到你预期的1, 1和2, 2输出了。
内容的提问来源于stack exchange,提问作者dale
相关产品推荐
相关产品推荐

