基于首个选择器值从JSON加载曲目到选择器的报错排查
报错核心原因
触发这个错误的本质是JSON数据结构读取路径错误,同时存在XHR逻辑缺失、变量引用问题,具体问题点:
data.Albums[artistValue]在你的JSON结构里是数组类型,不是直接存曲目信息的对象,直接访问.tracks会拿到undefined- 在
undefined基础上继续访问.title得到的值还是undefined,把undefined传给要求入参为对象的Object.entries()方法,就会抛出Cannot convert undefined or null to object错误 - 循环内使用了从未定义的
artist变量赋值给选项,就算前面逻辑跑通,选项内容也会显示异常 - XHR请求没有调用
send()方法发送,也没有判断请求加载状态,第一次触发更新时响应内容为空,解析JSON也会报错 - 切换艺术家时没有清空第二个选择器的旧选项,会出现重复内容堆叠的问题
可直接运行的修正代码
HTML部分(原有代码无需修改)
<select onchange="Update()" id="artistSelector"></select> <select id="trackSelector"></select>
JavaScript部分
const url = './jukebox.json'; const request = new XMLHttpRequest(); // 全局缓存加载完成的专辑数据,避免重复解析 let albumData = null; request.open('GET', url, true); // 请求加载完成回调 request.onload = function() { if (request.status >= 200 && request.status < 300) { albumData = JSON.parse(request.responseText); const artistSelector = document.getElementById('artistSelector'); // 初始化填充艺术家选择器 Object.keys(albumData.Albums).forEach(artistKey => { const artistOption = document.createElement('option'); artistOption.value = artistKey; // 取专辑信息里的正式艺术家名做显示文本 artistOption.textContent = albumData.Albums[artistKey][0].artist; artistSelector.appendChild(artistOption); }); // 初始化加载默认选中艺术家的曲目 Update(); } } // 发送请求,原有代码漏了这一步 request.send(); function Update() { const artistValue = document.getElementById("artistSelector").value; const trackSelector = document.querySelector('#trackSelector'); // 清空上一次的旧选项 trackSelector.innerHTML = ''; // 按JSON结构正确读取曲目列表:对应艺术家的专辑数组取第一个元素,再取tracks数组 const tracks = albumData.Albums[artistValue][0].tracks; // 遍历曲目数组生成选项 tracks.forEach(trackItem => { const option = document.createElement('option'); option.textContent = trackItem.title; option.value = trackItem.title; trackSelector.appendChild(option); }); }
逻辑说明
- 页面加载时自动请求JSON数据,完成后先填充艺术家选择器的选项,再默认加载第一个艺术家的曲目
- 切换艺术家时,先清空曲目选择器的旧内容,再遍历对应艺术家的曲目数组生成新选项
- 全程不需要调用
Object.entries()处理曲目数组,直接用数组的forEach方法遍历即可,从根源上避免入参类型错误
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

