权限校验不应依赖try-catch控制流程,而应分三段:前置同步判断(if检查)、必要异步校验(await+try-catch)、错误分类处理;finally仅适合收尾操作,不可用于权限状态变更。

在 async 业务逻辑中做权限校验时,try-catch 不是校验手段,而是错误兜底机制。权限校验本身应是主动判断、提前拦截的过程;只有当校验逻辑内部抛出异常(比如 API 调用失败、token 解析出错、后端返回 403/401 且被显式 throw),try-catch 才会起作用。
权限校验该放在 try 块里吗?
不是“放不放”的问题,而是“要不要让它可能抛异常”。常见合理场景:
- 调用
await checkPermission('/api/order')这类异步鉴权接口,它内部用fetch请求权限服务,失败时throw new Error或根据!res.ok主动抛错 → 此时适合用 try-catch 捕获并跳转登录页或提示无权限 - 解析本地 token(如
jwt.decode(token))时发生SyntaxError→ 同步异常,可被外层 try-catch 捕获 - 校验角色字段
user.role === 'admin'是纯同步判断,不会抛错,不需要 try-catch;若误写成user.roles.includes('admin')而user.roles是 undefined,这会触发TypeError,虽能捕获,但更推荐先做防御性检查:Array.isArray(user.roles)
典型错误:把权限判断当成异常来 catch
以下写法不可取:
-
if (!hasPermission) { throw new Error('no access') }然后靠 catch 处理 → 逻辑上本应走 if-else 分支,不该依赖异常流控制 -
try { renderAdminPanel() } catch { redirectTo403() }→renderAdminPanel是纯前端渲染,不抛错,catch 永远不执行 - 在权限校验前没 await,却指望外层 try-catch 捕获异步结果 → 如
checkPermission().then(...)写在 try 里,但没 await,错误仍会冒泡到全局
推荐结构:校验 + 异常防护双结合
一个健壮的权限流程通常包含三段:
-
前置同步判断:检查 token 是否存在、是否过期(用
Date.now() )、角色字段是否合法 —— 这些用 if 返回明确状态,不抛错 - 必要异步校验:如向后端确认当前用户对某资源是否有操作权限 → 这个请求必须 await,并包裹在 try-catch 中
- 错误分类处理:catch 到错误后,区分是网络失败、认证失效(401)、权限不足(403)还是未知错误,分别响应(刷新 token / 跳登录 / 提示无权限 / 上报监控)
注意 finally 不适合做权限清理
finally 会在任何情况下执行,包括权限校验成功和失败。但它不适合用来“撤销权限”或“退出登录”,因为:成功时你不该退出,失败时你可能正要跳转,此时执行清理反而干扰流程。真正需要收尾的操作(如关闭 loading、释放锁)可以放在这里,但权限状态变更应由 try 或 catch 明确控制。











