Vue Router的router.push()返回Promise,try-catch无法直接捕获因其不抛同步异常;必须await后用try-catch处理reject,如导航被中止、守卫拒绝或组件加载失败等场景。

路由跳转失败本身不会自动抛出 JavaScript 异常,所以直接用 try-catch 包裹 router.push() 或 router.replace() 是捕获不到错误的——它返回的是一个 Promise,而 Promise 的 rejection 必须显式处理。
为什么 try-catch 无法直接捕获路由跳转失败
Vue Router 的导航方法(如 router.push)在 v4+(组合式 API 常用版本)中返回 Promise,但这个 Promise 只有在导航被 明确取消或中断 时才 reject,比如:
- 导航守卫中调用
next(false)或抛出错误 - 守卫中返回
Promise.reject()或throw new Error() - 目标路由组件异步加载失败(例如
defineAsyncComponent报错) - 用户在跳转中途点击浏览器后退,导致当前导航被中止(
NavigationFailureType.aborted)
如果只是目标路由不存在、404 或重定向失败,默认不会 reject,而是静默完成到 fallback 路由(如 /not-found),此时 Promise 仍 resolve。
正确捕获:await + try-catch 包裹 Promise
必须 显式 await 导航方法,并用 try-catch 捕获其 rejection:
✅ 正确写法:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
import { useRouter } from 'vue-router'<br>export default {<br> setup() {<br> const router = useRouter()<br> <br> const handleJump = async () => {<br> try {<br> await router.push('/admin/dashboard')<br> // 成功跳转后可执行后续逻辑<br> } catch (error) {<br> // 这里能捕获被 reject 的导航错误<br> if (error.name === 'NavigationFailure') {<br> console.warn('导航失败:', error.message, error.type)<br> } else {<br> console.error('未知跳转异常:', error)<br> }<br> }<br> }<br> <br> return { handleJump }<br> }<br>}
区分不同类型的导航失败
Vue Router 提供了 isNavigationFailure 工具函数和 NavigationFailureType 枚举,便于精准判断失败原因:
-
NavigationFailureType.redirected:被导航守卫重定向(通常不视为错误) -
NavigationFailureType.aborted:导航被用户行为(如后退)或新导航覆盖而中止 -
NavigationFailureType.cancelled:守卫中调用next(false)或返回false -
NavigationFailureType.duplicated:尝试跳转到当前相同路由(默认静默,不 reject;除非配置scrollBehavior报错)
使用方式:import { isNavigationFailure, NavigationFailureType } from 'vue-router',然后在 catch 中判断 isNavigationFailure(error) 和 error.type。
更健壮的实践:避免过度依赖 Promise reject
很多“跳转失败”场景(如 404、权限不足)更适合在 全局前置守卫 或 路由级 beforeEnter 中拦截并统一处理,而不是等 Promise reject 后再兜底:
- 在
router.beforeEach中检查权限,return '/login'或throw createError(...) - 对敏感路由添加
beforeEnter: (to, from) => { if (!hasAuth()) throw new Error('no access') } - 配合
router.isReady()确保路由系统就绪后再执行跳转,避免因初始化未完成导致意外 reject
这样既提升用户体验,也减少业务层对 Promise 错误处理的耦合。


















