JS forEach循环无法等待内部异步函数执行导致顺序异常怎么解决?
问题根因
test2内部的setTimeout属于异步宏任务,不会阻塞同步代码执行,且原test2没有显式返回值,调用后直接返回undefined,不可能拿到setTimeout内部的返回结果- 普通
forEach遍历的回调函数不支持异步等待,即使给回调加async标识也会同时触发所有异步任务,无法实现按顺序执行,会一次性跑完所有循环逻辑,等同步代码执行完毕后才会触发setTimeout的回调
解决方案
采用Promise + async/await改造异步逻辑,同时将forEach替换为支持异步等待的for...of循环即可实现需求:
改造后完整代码
$('#sr').click(function() { test(); }); // 加async标识标记为异步函数,内部才能使用await语法 var test = async function test() { var t1 = ["a", "b", "c"]; var t2 = ["d", "e", "f"]; // 替换forEach为for...of,支持按顺序等待异步任务 for (const item of t2) { // 等待test2执行完成拿到返回结果后再执行后续逻辑 const qqStr = await test2("QQ"); console.log(qqStr); console.log(item); t1.push(item); } console.log(t1); } // test2返回Promise,把异步执行的结果通过resolve抛出 var test2 = function test2(x) { return new Promise((resolve) => { setTimeout(function() { resolve(x); }, 1000); }) }
HTML部分无需改动,保持原有逻辑即可:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <input value="show result" type="button" id="sr" />
效果说明
改造后代码会按照预期顺序输出:每间隔1秒依次打印QQ、对应字母,三次循环结束后打印最终的["a","b","c","d","e","f"]数组。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

