如何同步发送Map中数组存储的URI请求,保证执行顺序?
实现Map中请求的顺序同步执行
原代码(one.tsx)
function fnOne() { var urlMap = new Map(); urlMap.set("1", ["https://thetestrequest.com/comments/1", "https://thetestrequest.com/comments/2", ... 100 length]) urlMap.set("2", ["https://thetestrequest.com/comments/4", "https://thetestrequest.com/comments/5", ... 15 length]) urlMap.forEach((value: any, key: any) => { console.log(key + " Loop"); const commentsXML : any = fnTwo(value); commentsXML.then((ResponseArray: any) => { console.log(key + " ResponseArray"); console.log(ResponseArray); }); }); } function fnTwo(value: any) { console.log("Inside fnTwo"); var d1 = fetch(value) .then(response => response.text()) .then(data => { console.log("Return response.text: " + new Date() + data); return data; }) .catch((error) => console.error("ERROR in fetch " + error)); return d1; }
注:原代码中
urlMap.put应为urlMap.set,Map对象的正确添加方法是set而非put
当前问题:请求并行执行,顺序不符合预期
实际控制台输出
- 1 Loop
- Inside fnTwo
- 2 Loop
- Inside fnTwo
- GET for 100 elements urlMap[0] (response date is 12:00:02). 3000 ms response time.
- GET for 15 elements urlMap[1] (response date is 12:00:01). 700 ms response time.
- Return response.text: 12:00:02 IST xml response for 100 elements
- 1 ResponseArray
- XML response for 100 elements
- Return response.text: 12:00:04 IST xml response for 15 elements
- 2 ResponseArray
- XML response for 15 elements
预期控制台输出
- 1 Loop
- Inside fnTwo
- GET for 100 elements urlMap[0]
- Return response.text: 12:00:02 IST xml response for 100 elements
- 1 ResponseArray
- XML response for 100 elements
- 2 Loop
- Inside fnTwo
- GET for 15 elements urlMap[1]
- Return response.text: 12:00:04 IST xml response for 15 elements
- 2 ResponseArray
- XML response for 15 elements
问题核心:forEach会同步遍历Map的所有条目,立即触发每个条目的fnTwo调用,而fetch是异步操作,不会阻塞后续遍历,导致两个请求并行发送,响应顺序取决于请求耗时,而非遍历顺序。
解决方案:使用async/await配合for...of实现顺序执行
将fnOne改为异步函数,通过for...of遍历Map的键值对,每次等待当前请求完成后再处理下一个条目:
async function fnOne() { var urlMap = new Map(); urlMap.set("1", ["https://thetestrequest.com/comments/1", "https://thetestrequest.com/comments/2", ... 100 length]) urlMap.set("2", ["https://thetestrequest.com/comments/4", "https://thetestrequest.com/comments/5", ... 15 length]) // 使用for...of遍历Map的entries,配合await实现顺序执行 for (const [key, value] of urlMap.entries()) { console.log(key + " Loop"); try { const responseArray = await fnTwo(value); console.log(key + " ResponseArray"); console.log(responseArray); } catch (error) { console.error("处理请求时出错: ", error); } } } function fnTwo(value: any) { console.log("Inside fnTwo"); return fetch(value) .then(response => response.text()) .then(data => { console.log("Return response.text: " + new Date() + data); return data; }) .catch((error) => { console.error("ERROR in fetch " + error); throw error; // 抛出错误让上层try/catch捕获 }); }
修改说明
- 将
fnOne标记为async函数,允许内部使用await关键字 - 替换
forEach为for...of遍历urlMap.entries(),因为forEach不支持异步等待逻辑 - 使用
await等待fnTwo返回的Promise完成,确保当前请求处理完毕后再进入下一次循环 - 在
fnTwo的catch块中抛出错误,让上层的try/catch可以捕获并处理异常,避免后续请求被意外中断
这样修改后,请求会严格按照Map的遍历顺序依次发送,必须等前一个请求的响应处理完成后,才会触发下一个请求,完全符合预期的同步执行逻辑。
内容的提问来源于stack exchange,提问作者Chidambaram L
相关产品推荐
相关产品推荐

