异步请求存入数组后forEach无输出?console.log数组却正常显示
问题分析:为什么
console.log(array)能看到数组元素,但forEach遍历无输出? 先看原代码:
async function apiRequest(id) { let res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`); let finalRes = await res.json(); return finalRes; } let array = []; async function main() { for (let i = 1; i <= 5; i++) { let res = await apiRequest(i); array.push(res); } } console.log(array); // 控制台能看到数组元素 array.forEach((element) => { console.log(element); // 无输出 }); main();
核心原因:异步代码执行顺序 + 浏览器控制台的动态特性
- 代码执行的先后逻辑
代码是从上到下同步执行的:
- 先声明空数组
array,接着立刻执行console.log(array)和array.forEach,这时候main()刚被调用,里面的异步请求还在等待响应,array还是空的。所以forEach遍历空数组,自然不会有任何输出。
- 控制台显示的“错觉”
你在控制台看到array有元素,是因为浏览器控制台对数组、对象这类引用类型做了特殊处理:它不会立刻显示执行console.log时的实时值,而是在你点开数组的时候才去读取最新的引用内容。等你点开控制台里的数组时,main()里的异步请求已经完成,array已经被填满了,但执行console.log(array)的那一刻,数组其实是空的。
你可以做个测试:把console.log(array)改成console.log([...array])(把数组浅拷贝成新数组),这时候控制台就会直接显示空数组,和forEach的表现完全一致。
解决方法
要等main()里的异步操作全部完成后,再去遍历数组,有两种常见方式:
方式1:把遍历逻辑放到main()内部
async function apiRequest(id) { let res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`); let finalRes = await res.json(); return finalRes; } let array = []; async function main() { for (let i = 1; i <= 5; i++) { let res = await apiRequest(i); array.push(res); } // 异步请求完成后再遍历 array.forEach((element) => { console.log(element); }); } console.log(array); // 执行时为空,点开控制台会看到填充后的数据 main();
方式2:用then()等待main()执行完成
async function apiRequest(id) { let res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`); let finalRes = await res.json(); return finalRes; } let array = []; async function main() { for (let i = 1; i <= 5; i++) { let res = await apiRequest(i); array.push(res); } } console.log(array); // 执行时为空,点开控制台会看到填充后的数据 // 等待main的异步操作完成后再遍历 main().then(() => { array.forEach((element) => { console.log(element); }); });
内容的提问来源于stack exchange,提问作者Raghavan Vidhyasagar
相关产品推荐
相关产品推荐

