Suspense 的核心是自动等待 #default 插槽内所有异步依赖(多组件、async setup、子组件 Promise)全部完成;应将并发请求分散至各子组件的 async setup 或 defineAsyncComponent 中,由 Suspense 统一聚合等待,避免父组件手动 Promise.all。

Suspense 的核心能力之一,就是自动等待它 #default 插槽内整个组件树中所有异步依赖完成——包括多个异步组件、多个 async setup()、甚至子组件内部的 Promise。它不是“等一个”,而是“等全部”。所以处理多个并发请求,关键不在手动合并 Promise,而在于让它们自然落入 Suspense 的等待范围。
确保所有异步逻辑都发生在 #default 插槽内部
Suspense 只对包裹在 #default 中的内容生效。只要把需要并发加载的组件或逻辑都放在这里,它就会自动聚合等待。
- 不要在父组件的 setup 或 data 中提前 await 多个接口——那会阻塞整个组件挂载,失去 Suspense 的声明式优势
- 每个子组件应各自负责自己的异步逻辑(比如用 async setup 或 defineAsyncComponent),然后统一被 Suspense 包裹
- 例如:订单页同时加载订单信息、商品列表、物流进度,就分别用三个独立的异步子组件,一起放进 #default
用 defineAsyncComponent 动态导入 + 内部异步数据获取
这是最常见也最推荐的方式:组件本身异步加载,内部再发起数据请求。Suspense 会同时等待组件代码下载和 setup 中的 Promise。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 子组件写法示例(OrderDetail.vue):
- export default { async setup() { const order = await api.getOrder(); const items = await api.getOrderItems(); return { order, items } } }
- 父组件只需:<Suspense><template #default><OrderDetail /></template><template #fallback><Skeleton /></template></Suspense>
- 即使 OrderDetail 内部发了两个请求,Suspense 也会等到两者都 resolve 后才显示内容
避免手动 Promise.all,除非有强顺序依赖
多数场景下不需要也不建议在父组件里用 Promise.all 手动聚合多个请求,因为这会绕过 Suspense 的自动协调机制,反而增加复杂度。
立即学习“前端免费学习笔记(深入)”;
- 手动聚合后返回的数据仍需通过 props 传给子组件,loading 状态又得自己维护,回到传统模式
- 只有当几个请求结果必须一起使用、且无法拆分到不同子组件时,才考虑在单个 async setup 中用 Promise.all
- 即便如此,也依然要把它放在 #default 插槽内的组件里,而不是 Suspense 外层
错误与加载状态由插槽统一控制
Suspense 本身不直接暴露 loading 或 error 状态变量,但提供了清晰的生命周期钩子和事件支持:
- onSuspenseResolve:监听异步内容成功加载
- onSuspenseFallback:监听进入 fallback 状态
- 错误处理建议放在子组件内部(比如 try/catch + errorComponent 配置),或用全局错误边界配合 Suspense
- #fallback 插槽可以是骨架屏、Spinner,甚至带重试按钮的自定义组件,无需为每个请求单独写提示

















