为何JavaScript中全局变量在异步函数外打印为undefined?
问题
声明了全局变量latitude、longitude、IPLocation,调用异步函数start为变量赋值后,在函数外打印IPLocation显示undefined,但在start函数内打印该变量却正常。代码如下:
let latitude, longitude, IPLocation; start(path) console.log(IPLocation) // 输出undefined async function start(path) { IPLocation = await getData(path); latitude = IPLocation.location.lat; longitude = IPLocation.location.lng; console.log(IPLocation) // 正常输出数据 } async function getData(path) { const data = await fetch(path); const scrampled = await data.json(); parsed = await JSON.parse(JSON.stringify(scrampled)); return parsed }
原因
核心是异步函数的执行特性:
start是异步函数,调用它时会立即返回一个Promise,不会阻塞后续代码的执行。- 你调用
start(path)后立刻执行console.log(IPLocation),这时候await getData(path)还没完成(网络请求仍在进行),IPLocation还未被赋值,所以输出undefined。 - 而
start函数内部,await getData(path)会等待异步操作完成,拿到数据后才给IPLocation赋值,之后再打印,因此能正常输出。
另外提个细节:getData里的await JSON.parse(JSON.stringify(scrampled))是多余的,JSON.parse是同步操作,不需要加await;而且data.json()已经把响应解析成JSON对象了,这里的JSON.parse(JSON.stringify(scrampled))只是做了一次深拷贝,完全没必要用await。
解决办法
要在IPLocation赋值完成后再打印,有两种常用方式:
方式一:用立即执行异步函数包裹调用
let latitude, longitude, IPLocation; // 用异步立即执行函数包裹,等待start执行完成 (async () => { await start(path); console.log(IPLocation); // 正常输出 })(); async function start(path) { IPLocation = await getData(path); latitude = IPLocation.location.lat; longitude = IPLocation.location.lng; console.log(IPLocation); } async function getData(path) { const data = await fetch(path); const scrampled = await data.json(); const parsed = JSON.parse(JSON.stringify(scrampled)); // 去掉多余的await return parsed; }
方式二:用Promise的then方法
let latitude, longitude, IPLocation; start(path).then(() => { console.log(IPLocation); // 正常输出 }); async function start(path) { IPLocation = await getData(path); latitude = IPLocation.location.lat; longitude = IPLocation.location.lng; console.log(IPLocation); } async function getData(path) { const data = await fetch(path); const scrampled = await data.json(); const parsed = JSON.parse(JSON.stringify(scrampled)); // 去掉多余的await return parsed; }
内容的提问来源于stack exchange,提问作者ahmed_bsher2
相关产品推荐
相关产品推荐

