不能在路由守卫中用 generator 阻塞渲染等待鉴权,因 js 单线程非阻塞,yield 不等待 promise;应改用守卫做快速准入判断、组件内异步校验并配合 loading 或兜底视图。

不能在路由守卫中用 Generator(如 function* + yield)精准阻塞页面渲染来等待鉴权结果。
Generator 无法真正“阻塞”异步流程
JavaScript 是单线程、非阻塞的,Generator 本身不处理异步等待。它只是提供一种可暂停/恢复的函数执行方式,但 yield 后的值不会自动等待 Promise resolve;它只是把 Promise 对象交出去,不会挂起 JS 执行栈或渲染进程。强行用 co 或手动迭代 generator 并不能让 Vue/React 的组件挂载暂停——框架早已开始解析、创建 vnode、甚至触发 mounted/hydration。
常见误解是:写个 function* authGuard() { yield verifyToken(); } 就能“等完再进页面”。实际上:
- 路由守卫(如
beforeEach、canActivate)要求返回布尔值、Promise 或重定向动作,不接受 Iterator 对象; - 即使你封装成 Promise(如
co(authGuard)),本质仍是 Promise 链,和直接return verifyToken()等价; - 所谓“阻塞渲染”在 SPA 中并不存在——路由跳转时,旧组件可能已卸载、新组件正在初始化,UI 线程不会因 JS 暂停而卡住。
真正可控的鉴权时机只有两个节点
前端无法也不该“拦住渲染”,而应控制「何时开始渲染受保护内容」:
-
路由守卫阶段:只做快速准入判断(如 token 存在性、过期时间检查),返回同步布尔值或轻量 Promise(如读 localStorage + 解析 JWT payload)。耗时操作(如调用
/api/auth/verify)必须异步,且需配合 loading 状态或占位 UI; -
组件内部阶段:进入页面后,用
useEffect(React)或onBeforeRouteEnter+async setup(Vue 3)发起鉴权请求,根据响应决定是否渲染主内容、显示权限不足提示,或重定向。
推荐替代方案:组合式异步守卫 + 组件级兜底
以 Vue Router 为例,实际可行做法:
- 全局守卫中检查本地 token 是否存在且未过期(同步)→ 快速放行或跳登录;
- 对需强校验的路由(如后台首页),配置
meta: { requiresServerCheck: true }; - 在对应页面组件的
setup()中:
① 显示 skeleton 或 loading 状态;
② 调用authService.verifyWithRole()获取完整权限;
③ 若失败,router.replace('/403')或展示无权限视图。
React Router v6+ 同理:用 loader 函数(支持 async)预加载鉴权结果,并配合 errorElement 处理失败场景,比试图“阻塞”更自然、更符合数据流设计。











