async/await的执行机制属于异步还是同步?
你对await的行为描述存在两处核心认知偏差,才会产生「看起来是同步」的误解:
核心误区1:把「当前函数上下文的暂停」等同于「全局线程的同步阻塞」
await 暂停的从来不是JS整个主线程的执行,仅仅是当前async函数自身的执行上下文。在等待Promise resolve的过程中,主线程会跳出当前async函数,继续执行调用栈里剩下的所有同步代码,等同步代码全部清空、Promise状态变为resolved之后,才会把await后面的逻辑加入微任务队列,等时机合适再回到函数里继续执行。
你可以跑下这段测试代码直观看区别:
console.log('1. 全局同步代码启动') async function demo() { console.log('2. async函数内await之前的代码,调用时同步执行') await new Promise(resolve => setTimeout(() => { console.log('4. 等待1秒后Promise被resolve') resolve() }, 1000)) console.log('5. await后的代码,等Promise落定才执行') } demo() console.log('3. 调用demo函数后的全局同步代码,完全没被await阻塞')
如果await是真同步行为,执行顺序应该是1→2→等1秒→4→5→3,但实际运行的顺序是1→2→3→等1秒→4→5。这就是最本质的区别:同步阻塞会卡住整个线程,所有其他代码都要等阻塞结束才能跑;而await的暂停是主动让出主线程,不耽误其他任务执行。
核心误区2:误解了async/await的实际作用
async/await从来不是用来「让函数以异步方式运行」的,它只是基于Promise的语法糖,核心价值是把原本需要嵌套.then()的异步回调逻辑,拍平成从上到下的线性写法,降低异步代码的理解和维护成本。
你可以把await直接理解成.then()的语法替代:await 后面的代码,本质上会被自动包装到对应Promise的.then()回调里,执行逻辑和手写Promise链没有任何区别。比如上面的demo函数,去掉async/await改写之后的执行顺序完全一致:
function demo() { console.log('2. 函数内同步代码执行') return new Promise(resolve => setTimeout(() => { console.log('4. 等待1秒后Promise被resolve') resolve() }, 1000)).then(() => { console.log('5. 原await后的逻辑,被自动包装成then回调') }) }
你不会觉得.then()是同步行为,自然也不该把await的线性写法体验等同于同步阻塞。
总结
你觉得await表现像同步,只是因为async函数内部的代码写起来是逐行线性的,符合你写同步代码的思维习惯,但这只是语法层面的体验优化:
- 它不会阻塞主线程,等待Promise期间其他同步代码正常执行
- 它没有创造新的异步能力,底层完全依赖Promise和事件循环的异步调度逻辑
- 它只暂停当前async函数的后续执行,不会影响函数外的代码运行
内容的提问来源于stack exchange,提问作者randomsizzler

