fetch获取数据后数组forEach仅显示首个元素的问题咨询
问题分析与解决
你的问题核心是没搞懂两个关键点:fetch的异步执行顺序,以及浏览器控制台对引用类型的“实时显示”特性。
1. 代码执行顺序拆解
JavaScript是单线程的,异步任务(比如fetch)会被放到任务队列,等同步代码全部执行完才会运行:
- 先执行同步代码:初始化
tt、Orders数组,Orders.push(tt)(此时数组长度为1)。 - 调用
fetch(url):发起网络请求,但不会等待结果,直接跳过继续执行后面的同步代码。 - 执行
console.log(Orders)、Orders.forEach(...)、console.log('test2'):这时候fetch还没返回数据,Orders里只有最初的1个元素,所以forEach只打印第一个,访问Orders[3]自然是undefined。 - 等同步代码跑完,浏览器才会处理fetch的响应,执行
then回调里的代码,把data.tt1里的元素push到Orders中,此时数组长度变成30。
2. 为什么console.log(Orders)显示有30个元素?
这是浏览器控制台的“坑”:当你打印引用类型(比如数组、对象)时,控制台显示的是该引用的实时状态,而不是执行console.log那一刻的快照。你点开数组展开查看时,fetch的回调已经执行完了,所以看到30个元素,但实际执行console.log的瞬间,数组只有1个元素。
验证这个点很简单,把console.log(Orders)改成:
console.log(JSON.stringify(Orders)); // 打印执行时的快照,只会看到1个元素
3. 解决方法
所有依赖fetch返回数据的操作,必须放到then回调内部,或者用async/await语法让代码看起来更同步:
方法一:把forEach移到then回调里
var tt = {ttpart:"Fiat", ttdesc:"500", ttum:"white"}; var Orders = new Array(); Orders.push(tt); fetch(url) .then(res => res.json()) .then((data) => { for ( tt of data.tt1) { Orders.push(tt); const listItem = document.createElement("h1"); } // 现在Orders已经有全部30个元素了 Orders.forEach((element) => { console.log(element); }); }) .catch(err => { throw err }); console.log('test2');
方法二:用async/await(更直观)
async function fetchData() { var tt = {ttpart:"Fiat", ttdesc:"500", ttum:"white"}; var Orders = new Array(); Orders.push(tt); try { const res = await fetch(url); const data = await res.json(); for ( tt of data.tt1) { Orders.push(tt); const listItem = document.createElement("h1"); } // 这里可以安全访问完整的Orders数组 console.log(Orders); Orders.forEach((element) => { console.log(element); }); } catch (err) { throw err; } } fetchData(); console.log('test2');
注意:async/await本质还是异步,console.log('test2')依然会在fetch请求完成前执行,这是正常的。
内容的提问来源于stack exchange,提问作者Andrzej Litwinski
相关产品推荐
相关产品推荐

