Vue 3.4+ 支持顶层 await,但需 script setup 显式标注 async、TS 配置 es2022、配合 Suspense 使用,并推荐 Promise.all 并行请求。

Ainative Vue Sdk
使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……
下载
<script setup> 中使用顶层 await 是 Vue 3.4+ 官方支持的特性,但必须满足几个硬性条件,否则会报错或行为异常。它不是“随便写个 await 就行”,而是需要编译器、类型系统和运行时协同配合。
<h3>必须加 async 关键字声明 script setup
<p>整个 <script setup> 标签必须显式标注 <strong>async,否则即使写了顶层 await,组件也不会被识别为异步组件,Suspense 无法捕获加载状态,数据可能未就绪就渲染。
<p>✅ 正确写法:
<pre class='brush:php;toolbar:false;'><script setup lang="ts" async>
import { ref } from 'vue'
const list = ref<any[]>([])
const res = await fetch('/api/users')
list.value = (await res.json()).data
</script></pre>
<p>❌ 错误写法(不加 async):
<pre class='brush:php;toolbar:false;'><script setup lang="ts">
const res = await fetch('/api/users') // 编译报错或运行时挂起
</script></pre>
<h3>项目配置要支持顶层 await
<p>TypeScript 需开启 es2022 或更高版本模块支持,否则 ESLint 或 TS 编译器会报 <em>Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022'...。<p><span>立即学习“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)”;
<ul>
<li>确保 <font color="red">tsconfig.json 中包含:<code>"module": "es2022" 和 <code>"target": "es2022"
<li>Vetur 用户务必禁用 —— 它不支持 Vue 3 的顶层 await 语法校验,会持续报红;改用 Volar
<li>使用 Vite 创建的项目默认已配好,但老项目升级后常遗漏此项
<h3>配合 Suspense 控制加载态
<p>顶层 await 会让组件变成异步组件,此时必须用 <strong>Suspense 包裹,否则组件会白屏或卡在 loading 状态。
<pre class='brush:php;toolbar:false;'><template>
<Suspense>
<template #default>
<UserList />
</template>
<template #fallback>
<p>Loading...</p>
</template>
</Suspense>
</template></pre>
<p>注意:<code>#default 模板里的组件(如 UserList)内部用了顶层 await,才会被 Suspense 捕获;纯同步组件放进去无意义。
<h3>多个并行请求建议用 Promise.all
<p>避免串行等待影响性能。顶层 await 支持直接解构 Promise.all 结果:
<pre class='brush:php;toolbar:false;'><script setup lang="ts" async>
import { ref } from 'vue'
const [usersRes, rolesRes] = await Promise.all([
fetch('/api/users'),
fetch('/api/roles')
])
const users = ref((await usersRes.json()).data)
const roles = ref((await rolesRes.json()).data)
</script></pre>
<p>这样两个接口真正并行发出,总耗时≈较长的那个,而不是相加。</script>