调用带await的async异步函数后全局变量赋值不生效是什么原因?
问题核心原因
你遇到的问题不属于作用域问题,本质是异步代码的执行时序不符合你的预期。
所有async标记的函数,只要在内部碰到await关键字,会立刻暂停当前函数的执行,让出主线程执行后续的同步代码,直到await等待的异步操作完成后,才会回到async函数内部继续执行剩余代码。
你的代码实际执行顺序是:
- 全局初始化
seasonStart、seasonID为空字符串 - 调用
getCurrentSeasonapi(getCurrentSeasonURL),函数运行到const response = await fetch(url);时,因为fetch是异步网络请求,所以直接暂停getCurrentSeasonapi的执行,回到主线程继续执行后续代码 - 直接运行
console.log(seasonStart);,此时请求还未返回,setSeasonInfo根本没执行,变量还是初始空值 - 等主线程所有同步代码执行完毕,且fetch请求拿到返回结果后,才会回到
getCurrentSeasonapi继续执行剩余逻辑,解析JSON、调用setSeasonInfo给全局变量赋值,所以setSeasonInfo内部的打印能输出正确值。
为什么你的测试用例表现不同
你写的测试用例里的async函数内部没有await任何异步操作,会直接同步执行完成,所以调用changeTest()后会立刻把test改成100,后续代码当然能拿到修改后的值。如果给测试用例加个异步等待逻辑,就能复现你实际遇到的问题:
var test = 1; async function changeTest() { // 增加100ms延迟模拟网络请求 await new Promise(resolve => setTimeout(resolve, 100)) test = 100; } document.getElementById("first").innerHTML = test + `<br>` + 'Run Function:' + `<br>`; changeTest(); // 这里输出还是1,和你实际场景的空字符串表现一致 document.getElementById("first").innerHTML += test
修复方案
如果要保证打印时变量已经被赋值,需要等待异步函数执行完成再运行后续逻辑,两种常用实现方式:
- 用
await等待异步函数执行完成(注意await只能在async函数内部使用,可以用自执行async函数包裹):
(async () => { await getCurrentSeasonapi(getCurrentSeasonURL); console.log(seasonStart); })()
- 用
Promise.then添加回调,异步函数执行完成后自动触发回调:
getCurrentSeasonapi(getCurrentSeasonURL).then(() => { console.log(seasonStart); })
内容的提问来源于stack exchange,提问作者J.Doe
相关产品推荐
相关产品推荐

