async 关键字如何改变函数的执行行为

作者:袖梨 2026-07-12
async函数自动返回Promise,即使return普通值也等价于Promise.resolve();await仅在async函数内合法,暂停执行但不阻塞主线程,等待Promise完成后再继续。

async 关键字本身不改变函数的同步执行逻辑,而是让函数**自动返回一个 Promise**,并允许在函数体内使用 await 暂停异步等待。

函数返回值变成 Promise

加了 async 的函数,哪怕 return 一个普通值(比如 return 42),实际返回的也是一个已 resolve 的 Promise:

  • async function f() { return 42; } → 调用 f() 返回 Promise.resolve(42)
  • 如果函数抛出错误,自动变成 Promise.reject(error)
  • 即使函数体里没有 await,也始终返回 Promise,这是强制语义

启用 await 语法

只有在 async 函数内部,才能合法使用 await。它会暂停当前 async 函数的执行(但不阻塞主线程),等待右侧 Promise settle 后继续:

  • await fetch('/api') 会等网络请求完成,再往下走
  • await 只对 Promise 生效;对普通值,会立即返回(等价于 Promise.resolve(value)
  • await 不是“让代码变慢”,而是让逻辑按顺序写,避免嵌套回调

执行时机没变,但调用方式变了

async 函数仍是同步开始执行的(函数体第一行立刻运行),只是遇到 await 才“让出”控制权:

  • 函数体开头的同步代码(比如 console.log)仍立即执行
  • await 后面的代码被放入微任务队列,等当前同步任务结束后才运行
  • 调用 async 函数必须用 .then()await 处理返回的 Promise,不能直接取返回值

不能在顶层 await(除非模块顶层)

因为 await 只能在 async 函数里用,所以想在模块最外层等待异步操作,需包一层 async IIFE 或启用 top-level await(ES2022+,仅限模块环境):

  • await fetch('/data');(直接写在 script 最外层会报错)
  • (async () => { const res = await fetch('/data'); })();
  • ✅ 在 .mjs 文件或支持的环境中:顶层 await fetch('/data');
不复杂但容易忽略

相关文章

精彩推荐