如何将XMLHttpRequest响应存为外部可访问变量及fetch async/await问题
所有问题的本质是异步代码的执行顺序问题:网络请求属于耗时的异步操作,JS引擎会先执行完所有同步代码,再处理异步返回的结果,所以你在请求刚发起时就去读变量,自然是未赋值的状态。
1 XMLHttpRequest 场景解决方案
你可以在外部作用域声明变量存储结果,但必须保证只有请求完成后才访问这个变量,所有依赖该数据的逻辑要放在回调触发后执行:
// 外部作用域声明存储结果的变量 let responseResult = null const xhr = new XMLHttpRequest(), method = "GET", url = "https://developer.mozilla.org/"; xhr.open(method, url, true); xhr.onreadystatechange = function () { if(xhr.readyState === XMLHttpRequest.DONE) { const status = xhr.status; if (status === 0 || (status >= 200 && status < 400)) { // 请求成功后给外部变量赋值 responseResult = xhr.responseText // 调用后续处理逻辑,传入拿到的结果 processData(responseResult) } } }; xhr.send(); // ❌ 这里直接读取会拿到null,因为请求还没返回,回调还没执行 // console.log(responseResult) // ✅ 所有依赖请求结果的逻辑都放在这个函数里执行 function processData(data) { console.log('获取到的响应内容:', data) // 后续业务逻辑写在这里即可 }
2 fetch + async/await 场景解决方案
async 修饰的函数天生返回 Promise 对象,你直接调用拿到的不是函数内部return的结果,而是Promise实例。同时外部的alert是同步代码,会优先于异步的fetch逻辑执行,所以出现了你看到的弹窗顺序颠倒的问题。
可以用两种方式正确拿到结果:
方式1:用 .then 接收异步返回值
const getData = async function (filePath) { const response = await fetch(filePath) const myData = await response.text() alert(myData) return myData } // 用.then接收异步返回的结果 getData('./2021WeatherData.csv').then(theData => { alert(theData) // 所有需要用到theData的逻辑都写在这里 })
方式2:把所有逻辑放在async上下文中用await取值
const getData = async function (filePath) { const response = await fetch(filePath) const myData = await response.text() alert(myData) return myData } // 把后续逻辑都包在async函数里,用await拿结果 async function main() { const theData = await getData('./2021WeatherData.csv') alert(theData) // 后续用到theData的逻辑都写在这里 } main()
核心规则总结
- 所有异步操作(网络请求、定时器、事件回调)的结果,都不能直接在同步代码中获取,必须等异步操作完成后,在回调函数、
.then方法或者await后面的代码中才能访问 - 不要尝试把异步结果直接赋值给全局变量后在同步代码中直接使用,JS的执行顺序不支持这种操作
内容的提问来源于stack exchange,提问作者SunnyNonsense
相关产品推荐
相关产品推荐

