如何在JavaScript中确保含异步操作的for循环执行完成后再运行后续代码
问题原因
你遇到的输出顺序异常是JavaScript异步执行机制导致的:fetch是异步API,调用后会立即返回,后续的同步代码console.log('loop is finished!')会优先执行,而请求成功后的then回调需要等网络请求完成、数据返回后才会触发,自然就出现了日志顺序颠倒的情况。
解决方案
方案1:将后续逻辑移入回调
直接把需要等循环结束后执行的代码,放到then回调的末尾即可:
fetch('http://localhost:3000/pet/'+pet) .then(res => res.json()) .then(data => { const newData = data; for (var x in newData) { finalpetName.push(newData[x].petName); console.log('pet' + x + 'is retrieved'); }; // 循环执行完成后再运行后续任务 console.log('loop is finished!'); }) .catch(err => { console.error(err) });
如果需要兼容请求失败的场景,也可以把逻辑放到finally回调中,无论请求成功或失败都会执行:
fetch('http://localhost:3000/pet/'+pet) .then(res => res.json()) .then(data => { const newData = data; for (var x in newData) { finalpetName.push(newData[x].petName); console.log('pet' + x + 'is retrieved'); }; }) .catch(err => { console.error(err) }) .finally(() => { console.log('loop is finished!'); });
方案2:使用async/await语法(可读性更高)
把逻辑包裹在async函数中,用await等待异步请求执行完成后再运行后续代码:
// 封装为async函数 async function getPetNames() { try { const res = await fetch('http://localhost:3000/pet/'+pet); const newData = await res.json(); for (var x in newData) { finalpetName.push(newData[x].petName); console.log('pet' + x + 'is retrieved'); }; // 等待上述所有逻辑执行完成后再运行后续任务 console.log('loop is finished!'); } catch (err) { console.error(err); } } // 调用函数 getPetNames();
循环内部也存在异步操作的情况
如果你的循环迭代中也包含异步任务(比如每条数据需要单独发请求查询详情),可以用Promise.all批量等待所有任务完成:
async function getPetNames() { try { const res = await fetch('http://localhost:3000/pet/'+pet); const newData = await res.json(); // 把所有异步任务存到数组里 const tasks = Object.values(newData).map(async (item, index) => { // 示例:循环内部的异步操作 const extraInfo = await fetch(`http://localhost:3000/pet/detail/${item.id}`).then(res => res.json()); finalpetName.push(item.petName); console.log('pet' + index + 'is retrieved'); }) // 等待所有异步任务全部执行完成 await Promise.all(tasks); console.log('loop is finished!'); } catch (err) { console.error(err); } }
内容的提问来源于stack exchange,提问作者SGPascoe
相关产品推荐
相关产品推荐

