如何在Promise内部更新全局作用域中的变量?
问题分析与解决方法
问题根源
你的代码里fetch是异步操作,它会在后台发起请求、处理响应,不会阻塞后续同步代码的执行。而你写的console.log(json)和console.log(json.name)是同步代码,会在fetch的回调函数(第二个then里的代码)执行前就运行——这时候json还没被赋值,还是初始的undefined,自然读不到name属性。
解决方法
方法1:把操作放到then回调里
既然then里的代码会在请求完成、数据解析后执行,那就把需要使用json的代码都放在这个回调里:
let json; fetch('test.json') .then((response) => response.json()) .then((data) => { json = data; console.log(json); // 输出完整的JSON对象 console.log(json.name); // 输出"Alex C" });
方法2:用async/await简化异步代码
async/await是更直观的异步语法,能让异步代码看起来像同步代码:
// 封装成async函数 async function loadJsonData() { let json; // 等待fetch请求完成 const response = await fetch('test.json'); // 等待响应解析为JSON json = await response.json(); console.log(json); console.log(json.name); } // 调用函数 loadJsonData(); // 如果环境支持顶层await(比如现代浏览器、Node.js 14+),可以直接写: let json = await fetch('test.json').then(res => res.json()); console.log(json); console.log(json.name);
补充说明
JavaScript的异步任务会被放到任务队列中,等所有同步代码执行完毕后,才会依次执行任务队列里的回调。你原来的代码执行顺序是:
- 声明
json变量,初始值为undefined - 发起
fetch请求,将回调函数加入任务队列 - 执行
console.log(json)(输出undefined) - 执行
console.log(json.name)(报错,因为undefined没有name属性) - 等请求完成,执行
then里的回调,给json赋值
内容的提问来源于stack exchange,提问作者athariandre
相关产品推荐
相关产品推荐

