通过3个JSON文件创建嵌套菜单时遇异步请求无输出问题
问题核心:异步操作的执行时机错误
你遇到的问题是典型的异步代码执行顺序问题。$.getJSON 是异步请求,这意味着你发起请求后,代码会立刻继续往下走,不会等待请求完成。所以你的 $.each(json, ...) 代码在三个请求都还没返回数据的时候就执行了,这时候 json 还是个空对象,自然没有输出。
至于为什么 console.log(json) 看起来能返回对象,是因为浏览器的控制台有个「延迟求值」的特性:当你在控制台展开这个对象的时候,浏览器才会去读取它的实际内容,而这时候你的异步请求已经完成,数据已经填充进去了——但在代码执行到 console.log(json) 的那一刻,json 其实还是空的。
解决方案:等待所有异步请求完成后再处理数据
下面给你几种可行的解决方式,按推荐程度排序:
1. 使用 Promise.all(最推荐,并行请求+清晰逻辑)
jQuery 的 $.getJSON 会返回一个 Promise 对象,我们可以把三个请求的 Promise 放在数组里,用 Promise.all 等待所有请求都完成后再处理数据:
// 先发起所有请求,获取对应的Promise const categoryReq = $.getJSON("/api/category.json"); const subcatReq = $.getJSON("/api/subcat.json"); const subsubcatReq = $.getJSON("/api/subsubcat.json"); // 等待所有请求完成 Promise.all([categoryReq, subcatReq, subsubcatReq]) .then(([categoryData, subcatData, subsubcatData]) => { // 这里所有数据都已经获取到了 const json = { category: categoryData, subcat: subcatData, subsubcat: subsubcatData }; // 现在遍历就能正常输出了 $.each(json, function(i, v) { console.log(json[i]); }); // 在这里继续编写你的嵌套菜单构建逻辑 }) .catch(err => { // 处理请求失败的情况 console.error("加载菜单数据失败:", err); });
2. 使用 async/await(更简洁的异步写法)
如果你的运行环境支持 ES2017+(现代浏览器或经过编译的代码),可以用 async/await 让异步代码看起来像同步代码一样:
async function loadMenuData() { try { // 依次等待每个请求完成(也可以并行,和上面Promise.all效果一样) const categoryData = await $.getJSON("/api/category.json"); const subcatData = await $.getJSON("/api/subcat.json"); const subsubcatData = await $.getJSON("/api/subsubcat.json"); const json = { category: categoryData, subcat: subcatData, subsubcat: subsubcatData }; $.each(json, function(i, v) { console.log(json[i]); }); // 构建嵌套菜单 } catch (err) { console.error("加载数据出错:", err); } } // 调用这个异步函数 loadMenuData();
3. 回调嵌套(兼容旧环境,不推荐)
如果你需要兼容非常旧的浏览器(不支持 Promise),可以用回调嵌套的方式,但这种写法容易陷入「回调地狱」,代码可读性差:
$.getJSON("/api/category.json", function(categoryData) { $.getJSON("/api/subcat.json", function(subcatData) { $.getJSON("/api/subsubcat.json", function(subsubcatData) { const json = { category: categoryData, subcat: subcatData, subsubcat: subsubcatData }; $.each(json, function(i, v) { console.log(json[i]); }); // 构建菜单 }); }); });
内容的提问来源于stack exchange,提问作者Jack The Baker
相关产品推荐
相关产品推荐

