新闻中心
Angular Guard 结合多个 Observable 时失效的解决方案

本文旨在解决 Angular 应用中使用 Guard 结合多个 Observable 时,路由守卫失效的问题。通过 combineLatest 组合多个 Observable,并根据其结果决定是否允许用户访问特定路由。重点在于避免在 Observable 流中进行不必要的路由重定向,确保路由守卫的逻辑正确执行。
在 Angular 应用中,路由守卫(Guards)用于控制用户是否可以访问特定的路由。当需要根据多个条件(例如,用户角色、数据状态等)来决定是否允许访问时,通常会使用 RxJS 的操作符,如 combineLatest 或 zip,将多个 Observable 组合起来。然而,不当的使用方式可能导致路由守卫失效,例如,提前进行了不必要的路由跳转。
以下代码展示了一个常见的场景:需要判断用户是否是管理员,以及是否已经创建了 CV(简历),来决定是否允许用户访问 /new 页面。
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { Observable, combineLatest } from 'rxjs';
import { PersonsService } from '../services/persons.service';
import { map, finalize } from 'rxjs/operators';
import { AdministrationService } from '../services/administration.service';
import { CustomSnackbarService } from '../services/custom-snackbar.service';
@Injectable({
providedIn: 'root',
})
export class CanCreateNewCv implements CanActivate {
constructor(
private usersService: PersonsService,
private router: Router,
private administrationService: AdministrationService,
private snackbarService: CustomSnackbarService
) {}
canActivate(): Observable<boolean> | boolean | Promise<boolean> {
let isAllowed = false;
const cv$ = this.usersService
.getPersonsByPageAndFilter(10, 0)
.pipe(
map((data) => data.allDataCount > 0)
);
const admin$ = this.administrationService
.getCurrentUser()
.pipe(
map((currentUser) => currentUser.isAdmin || currentUser.isManager)
);
return combineLatest([cv$, admin$], (isCvUploaded, isAdminOrManager) => {
isAllowed = isAdminOrManager ? true : isCvUploaded ? false : true;
if (!isAllowed) {
this.router.n*igateByUrl('/list');
}
return isAllowed;
}).pipe(
finalize(() => {
if (!isAllowed)
this.snackbarService.open(
'This profile has CV already created!',
'Info'
);
})
);
}
}问题分析:
最初的代码存在一个问题:在 cv$ Observable 的 map 操作符中,如果用户已经创建了 CV,会立即执行 this.router.n*igateByUrl('/list') 进行路由跳转。这会导致无论用户是否是管理员,都会被重定向到 /list 页面,从而使管理员无法访
问 /new 页面。
解决方案:
正确的做法是将路由跳转的逻辑移动到 combineLatest 操作符的回调函数中。只有在 combineLatest 确定用户既不是管理员,也没有创建 CV 时,才进行路由跳转。 这样可以确保管理员始终可以访问 /new 页面,而普通用户只有在没有创建 CV 的情况下才能访问。
代码解释:
php商城系统(本地测试包)
PHP商城系统是国内领先商城系统,网店系统,购物系统,网上商城系统,B2C商城系统产品.同时也是一个商业的PHP开发框架。PHP 商城系统由内容、文章、会员、留言、订单、 财务、广告、短消息、数据库管理、营销推广、内置支付管理、商品配送管理、无限级分类、全站搜索等多个功能模块插件组成。在当今瞬机万变的市场环境中,快速高效的IT解决方案是您业务成功的关键。我们PHP商城系统能为您量身打造完全符合需求
0
查看详情
cv$ Observable: 从 PersonsService 获取用户 CV 数据,并使用 map 操作符将结果转换为一个布尔值,表示用户是否已经上传了 CV。
admin$ Observable: 从 AdministrationService 获取当前用户信息,并使用 map 操作符将结果转换为一个布尔值,表示用户是否是管理员或经理。
combineLatest([cv$, admin$], (isCvUploaded, isAdminOrManager) => { ... }): 使用 combineLatest 操作符将 cv$ 和 admin$ 两个 Observable 组合起来。当两个 Observable 都发出值时,combineLatest 会调用回调函数,并将两个 Observable 的最新值作为参数传递给回调函数。
-
回调函数中的逻辑:
- isAllowed = isAdminOrManager ? true : isCvUploaded ? false : true;:根据用户是否是管理员以及是否上传了 CV 来决定是否允许访问。如果用户是管理员,则允许访问;如果用户不是管理员,并且已经上传了 CV,则不允许访问;否则,允许访问。
- if (!isAllowed) { this.router.n*igateByUrl('/list'); }:只有在不允许访问的情况下,才进行路由跳转到 /list 页面。
finalize(() => { ... }): 使用 finalize 操作符在 Observable 完成时执行一些清理工作,例如显示提示信息。
总结:
在使用 RxJS 组合多个 Observable 来实现复杂的路由守卫逻辑时,需要特别注意路由跳转的时机。应该确保在所有必要的条件都满足后,再进行路由跳转,避免过早的跳转导致逻辑错误。将路由跳转的逻辑放在 combineLatest 的回调函数中是一个有效的解决方案。此外,清晰的逻辑判断和适当的注释可以提高代码的可读性和可维护性。
以上就是Angular Guard 结合多个 Observable 时失效的解决方案的详细内容,更多请关注其它相关文章!
# 服务端
# oa网站建设推广
# 小程序推广 素材网站
# 鄂州全网营销推广机构
# 黄冈品牌seo推广
# 渤海新区网络营销推广
# 网站推广有哪些方式好呢
# 农夫山泉营销推广方案PPT
# 餐饮网站建设最好
# 长春彩妆小红书推广营销
# 养老网站建设总结怎么写
# 重定向
# 如何实现
# js
# 如何使用
# 转换为
# 传了
# 回调
# 跳转
# 多个
# 营销推广
# gate
# 简历
# 路由
# 回调函数
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
微博网页版怎么开启两步验证_微博网页版账号安全两步验证设置方法
在WordPress中通过REST API获取BasicAuth保护的远程文章
C#如何安全地从用户上传的XML文件中读取数据? 验证与清理策略
Win10怎么制作U盘启动盘 Win10系统安装U盘制作教程【详解】
LINUX下如何进行磁盘分区_fdisk与parted工具在LINUX中的使用对比
内存疯狂猛猛涨价:主板销量直接腰斩!
怎么在mac上运行html代码_mac运行html代码方法【指南】
LINUX的I/O重定向是什么_深入理解LINUX中 >、>> 与 < 的区别
如何在Promise链中优雅地中断后续then执行
UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】
谷歌浏览器无痕模式怎么开 Chrome开启无痕浏览设置方法【教程】
4399免费游戏网址入口 4399小游戏免费入口点开即玩
HTML长属性值处理:表单action路径优化与代码规范应对
C++ explicit关键字防止隐式转换_C++构造函数安全规范
手机CPU怎么影响游戏体验_手机CPU对游戏性能的影响分析
如何将一个大型PHP应用拆分为多个Composer包_微服务与模块化架构的Composer实践
php源码怎么看淘宝客系统_看php源码淘宝客系统技巧
提升屏幕阅读器对“m”时间单位的播报准确性:HTML与CSS组合解决方案
wps文字怎么插入目录并自动更新_wps文字如何插入目录并自动更新方法
sublime如何优雅地处理行尾空格_sublime自动清理多余空白字符配置
腾讯QQ邮箱登录入口_QQ邮箱官方网站使用地址
J*aScript中向JSON对象添加新属性的正确姿势
Pygame教程:解决用户输入与游戏状态更新不同步问题
最新韩小圈网页版登录入口_官网在线观看官方链接
J*a里如何实现订单支付与库存同步功能_支付库存同步项目开发方法说明
Go Martini框架:动态服务解码后的图片内容
小米Civi 4录制视频过暗_小米Civi 4亮度优化
绝地鸭卫平a核爆刀流玩法攻略
126邮箱网页版官方入口 126邮箱账号在线登录平台
iCloud登录入口网页版 苹果iCloud官网登录
ArchiveofOurOwn小说阅读-ArchiveofOurOwn同人作品访问链接
Golang如何实现状态模式管理对象状态_Golang State模式实现技巧
Go语言中的*string:深入理解字符串指针
uc浏览器网页版极速入口 uc网页浏览器网页版流畅体验
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明
优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题
CSS子选择器:如何区分并样式化嵌套列表的子层级
CSS Flexbox与媒体查询:实现响应式布局中元素的并排与堆叠
深入理解Go语言中的指针类型:以*string为例
Excel Power Pivot如何处理XML数据源 构建高级数据模型
iwriter统一登录平台 iwrite账号密码登录页面
一加手机拍照效果不好怎么办 一加哈苏影像调校与专业模式使用教程【高手篇】
CKEditor 5 自定义构建在React应用中渲染失败的调试与解决
格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施
c++如何使用Catch2编写单元测试_c++简洁易用的BDD风格测试框架
composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?
Go语言HTML解析:利用Goquery精准获取指定元素内容
在Qt QML中通过Python字典动态更新TextEdit内容的教程
Composer的 "conflict" 字段有什么用_如何声明不兼容的包以避免依赖冲突


2025-10-06
浏览次数:次
返回列表