如何将JSON数据加载到JavaScript类属性并解决异步取值undefined问题
问题根本原因
fetch 是异步网络API,不会阻塞主线程执行。你在构造函数中调用loadData时,网络请求还在后台运行,构造函数不会等待请求返回就直接执行完毕。此时你访问实例的position等属性时,then回调里的赋值逻辑还没触发,自然得到的都是undefined。
解决方案
方案1:使用async/await改写,手动等待数据加载完成
调整类的结构,让loadData返回Promise,实例化后等待加载完成再操作属性:
class Element{ constructor(){ this.index = Math.floor(Math.random() * 89); this.position = null; this.symbol = null; this.name = null; this.color = null; } async loadData(){ const response = await fetch('./json/data.json'); const data = await response.json(); this.position = data[this.index].position; this.symbol = data[this.index].symbol; this.name = data[this.index].name; this.color = data[this.index].color; return this; } } // 调用示例 async function useElement() { const ele = new Element(); // 等待数据加载完成后再访问属性 await ele.loadData(); console.log(ele.name); // 可正常输出对应元素名称 }
方案2:使用静态工厂方法封装实例创建逻辑
避免外部手动处理加载等待,把实例化和数据加载逻辑封装到静态方法中,直接返回加载完成的实例,同时增加缓存避免重复请求:
// 全局缓存已加载的JSON数据 let elementDataCache = null; class Element{ constructor(index){ this.index = index; this.position = null; this.symbol = null; this.name = null; this.color = null; } static async create() { const index = Math.floor(Math.random() * 89); // 只有首次请求会拉取数据,后续创建实例直接复用缓存 if(!elementDataCache) { const response = await fetch('./json/data.json'); elementDataCache = await response.json(); } const ele = new Element(index); ele.position = elementDataCache[index].position; ele.symbol = elementDataCache[index].symbol; ele.name = elementDataCache[index].name; ele.color = elementDataCache[index].color; return ele; } } // 调用示例 async function useElement() { const ele = await Element.create(); console.log(ele.symbol); // 直接正常输出 }
内容的提问来源于stack exchange,提问作者ruben27
相关产品推荐
相关产品推荐

