JS异步请求构建嵌套对象异常,为何出现自引用结构?
问题:JSON数据构建嵌套对象出现自引用异常
我是JavaScript新手,在尝试从JSON文件获取数据构建嵌套对象时,发现生成的对象出现了自引用的异常结构。但手动构建相同结构的嵌套对象时,结果完全正常。
我的实现代码如下:
function fetchJson(name) { var dico = {}; fetch('../json/' + name + '.json') .then(response => response.json()) .then(data => { for (var x in data) { if(!isClubExist(dico, data[x].Club)) { // 判断俱乐部是否已存在于对象中 addClub(dico, data[x].Club); } addPlayer(dico, data[x].Club, data[x].Poste, fullName(data[x].Nom, data[x].Prénom)); } }) return dico; }
手动构建的示例代码:
var subjectObject = { "Front-end": { "HTML": ["Links", "Images", "Tables", "Lists"], "CSS": ["Borders", "Margins", "Backgrounds", "Float"] }, "Back-end": { "PHP": ["Variables", "Strings", "Arrays"], "SQL": ["SELECT", "UPDATE", "DELETE"] } } console.log(subjectObject);
问题原因及解决方法
1. 异步时序问题(核心问题)
fetch是异步操作,你调用fetchJson后会立刻返回空的dico对象,此时then回调里的填充逻辑还没执行。如果后续你直接打印这个dico,浏览器控制台可能因为引用特性显示后续修改后的状态,但这会导致你误以为对象结构有问题,同时也无法正确拿到填充完成的数据。
修正方式:让函数返回Promise,用async/await或then获取最终结果:
async function fetchJson(name) { var dico = {}; const response = await fetch('../json/' + name + '.json'); const data = await response.json(); for (let x in data) { // 把var换成let,避免潜在作用域问题 if(!isClubExist(dico, data[x].Club)) { addClub(dico, data[x].Club); } addPlayer(dico, data[x].Club, data[x].Poste, fullName(data[x].Nom, data[x].Prénom)); } return dico; } // 使用示例 fetchJson('你的文件名').then(dico => { console.log(dico); // 这里才能拿到正确填充后的对象 });
2. 辅助函数的逻辑错误(自引用的直接原因)
自引用异常大概率是addClub或addPlayer的实现写错了,比如不小心把dico本身赋值给了内部属性。
正确的辅助函数示例:
// 判断俱乐部是否存在 function isClubExist(dico, clubName) { return !!dico[clubName]; } // 添加俱乐部:创建新的空对象,而非赋值dico本身 function addClub(dico, clubName) { dico[clubName] = {}; } // 添加球员:按职位分类存入数组 function addPlayer(dico, clubName, position, fullName) { if (!dico[clubName][position]) { dico[clubName][position] = []; } dico[clubName][position].push(fullName); } // 拼接全名 function fullName(lastName, firstName) { return `${firstName} ${lastName}`; }
内容的提问来源于stack exchange,提问作者Hezaerd
相关产品推荐
相关产品推荐

