JavaScript fetch异步请求修改的全局变量为何外部无法获取更新值
原因说明
你的全局变量实际上已经被成功更新,只是你打印变量的时机早于fetch回调的执行时机。
fetch属于异步非阻塞API,JS主线程调用fetch后,不会等待HTTP请求返回结果,会直接向下执行后续的同步代码(也就是你写的三个console.log),这时候then内的回调函数还没有被触发,所以你打印的还是变量的初始值。等HTTP请求完成后,才会执行then回调修改全局变量,此时你再访问这几个变量就能拿到更新后的值。
普通同步函数是执行完全部逻辑才会继续执行后面的代码,所以修改全局变量后可以立即拿到新值,异步函数的执行时机和主线程同步代码是错开的,就出现了你遇到的现象。
解决方案
方案1:将依赖请求结果的逻辑放入回调中
所有需要用到fetch返回数据的逻辑,都放在then回调内部执行,确保执行时数据已经返回:
var arr = []; var dat=[1,2]; var prova = 5; fetch('https://ipinfo.io') .then(function(response) { return response.text(); }).then(function(text) { arr.push(text); dat = arr; prova=prova+1; // 所有依赖这三个变量的逻辑都写在这里 console.log(arr); console.log(dat); console.log(prova); document.getElementById('pText').innerHTML = dat[0]; });
方案2:使用async/await语法简化异步逻辑
async/await是Promise的语法糖,可以让异步代码的写法更接近同步代码,可读性更高:
async function getIpInfo() { var arr = []; var dat=[1,2]; var prova = 5; // 等待请求返回再执行后续代码 const response = await fetch('https://ipinfo.io'); const text = await response.text(); arr.push(text); dat = arr; prova=prova+1; // 后续可以直接使用更新后的变量 console.log(arr); console.log(dat); console.log(prova); document.getElementById('pText').innerHTML = dat[0]; // 可以把结果返回供外部使用 return { arr, dat, prova }; } // 调用异步函数,可通过then拿到返回结果 getIpInfo().then(result => { console.log('外部拿到的请求结果:', result); })
如果你确实需要把请求结果存为全局变量供其他模块调用,要确保其他模块访问这个变量的时机晚于fetch请求完成的时间,否则还是会拿到初始值。你可以通过增加请求完成状态标记、订阅回调等方式判断时机。
内容的提问来源于stack exchange,提问作者Walter Balzarotti
相关产品推荐
相关产品推荐

