Angular Guard 中 combineLatest 的正确使用姿势


angular guard 中 combinelatest 的正确使用姿势

本文旨在解决 Angular 应用中使用 combineLatest 结合多个 Observable 实现路由守卫时,可能出现的逻辑错误问题。通过分析一个实际案例,我们将深入探讨如何正确地使用 combineLatest,避免不必要的页面跳转,并提供清晰的代码示例和注意事项,帮助开发者构建更健壮的路由守卫。

在使用 Angular 开发应用时,路由守卫(Guards)是控制用户访问特定路由的重要机制。当需要根据多个条件(例如:用户权限、数据状态等)来决定是否允许用户访问某个路由时,常常会用到 RxJS 的 combineLatest 操作符。然而,不当的使用可能导致意料之外的行为,例如不正确的页面重定向。

问题分析

假设我们有一个场景:需要创建一个路由守卫 CanCreateNewCv,用于控制用户是否可以访问 /new 页面。该守卫需要同时检查两个条件:

  1. 用户是否已经创建了 CV(简历)。
  2. 用户是否是管理员或经理。

如果用户已经创建了 CV,并且不是管理员或经理,则不允许访问 /new 页面,并重定向到 /list 页面。如果用户是管理员或经理,则允许访问 /new 页面,无论是否已经创建了 CV。

以下是可能存在问题的代码:

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { Observable, combineLatest } from 'rxjs';
import { map, finalize } from 'rxjs/operators';
import { PersonsService } from '../services/persons.service';
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) => {
        if (data.allDataCount > 0) {
          this.router.n*igateByUrl('/list');
          return true;
        }
        return false;
      })
    );

    const admin$ = this.administrationService.getCurrentUser().pipe(
      map((currentUser) => {
        if (currentUser.isAdmin || currentUser.isManager) {
          return true;
        }
        return false;
      })
    );

    return combineLatest([cv$, admin$], (isCvUploaded, isAdminOrManager) => {
      isAllowed = isAdminOrManager ? true : isCvUploaded ? false : true;
      return isAllowed;
    }).pipe(
      finalize(() => {
        if (!isAllowed)
          this.snackbarService.open(
            'This profile has CV already created!',
            'Info'
          );
      })
    );
  }
}

上述代码的问题在于,无论用户是否是管理员或经理,cv$ Observable 都会尝试重定向到 /list 页面。这导致即使管理员或经理访问 /new 页面,也会被重定向。

CA.LA CA.LA

第一款时尚产品在线设计平台,服装设计系统

CA.LA 86 查看详情 CA.LA

解决方案

要解决这个问题,需要将页面重定向的逻辑移到 combineLatest 的回调函数中,只有当 isAllowed 为 false 时才进行重定向。同时,简化 cv$ 和 admin$ Observable 的 map 操作,直接返回布尔值。

以下是修改后的代码:

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { Observable, combineLatest } from 'rxjs';
import { map, finalize } from 'rxjs/operators';
import { PersonsService } from '../services/persons.service';
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 现在直接返回一个布尔值,指示用户是否已经上传了 CV。admin$ Observable 也做了类似的简化,直接返回一个布尔值,指示用户是否是管理员或经理。

关键的改变在于 combineLatest 的回调函数中,只有当 isAllowed 为 false 时,才会调用 this.router.n*igateByUrl('/list') 进行页面重定向。这样确保了只有当用户不是管理员或经理,并且已经上传了 CV 时,才会被重定向到 /list 页面。

注意事项

  • 避免在 Observable 中进行副作用操作: 尽量避免在 Observable 的 map 操作符中直接进行页面重定向等副作用操作。将这些操作移到 combineLatest 的回调函数中,可以更好地控制执行时机。
  • 理解 combineLatest 的行为: combineLatest 会在所有输入 Observable 都发出至少一个值后,才会发出值。因此,确保所有输入 Observable 都会发出值,否则守卫可能无法正常工作。
  • 错误处理: 在实际应用中,需要考虑错误处理的情况。如果 getPersonsByPageAndFilter 或 getCurrentUser 方法抛出错误,可能会导致守卫无法正常工作。可以使用 RxJS 的 catchError 操作符来处理这些错误。

总结

通过本文的分析,我们了解了如何正确地使用 combineLatest 结合多个 Observable 实现 Angular 路由守卫。关键在于理解 combineLatest 的行为,并避免在 Observable 中进行不必要的副作用操作。通过合理地组织代码,可以构建出更健壮、更可靠的路由守卫。

以上就是Angular Guard 中 combineLatest 的正确使用姿势的详细内容,更多请关注其它相关文章!


# 回调函数  # 路由  # 简历  # js  # 成都seo怎么选  # 谷歌seo逻辑  # seo值得买吗  # 黑龙江企业网站推广  # 池州seo优化哪家强  # 保定拼多多网站推广业务  # 关键词优化排名 詢问周a斯出色  # 汕头seo推广公司  # 厂家网站建设服务热线  # 成都seo网站结构  # 正确地  # 布尔值  # 无法正常  # 传了  # 移到  # 鼠标  # 才会  # 多个  # 重定向  # 回调  # gate 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 《360浏览器》自动保存账号密码设置方法  电脑从睡眠中被自动唤醒怎么办_Windows唤醒源事件查看与禁用【解决】  TikTok网页版入口快速访问 TikTok官网账号登录方法  优酷官网登录入口电脑版 优酷官网网址入口  苹果手机缓存怎么清除_苹果手机缓存如何清除iphone各版本操作步骤  在PHP环境中正确加载HTML资源:CSS样式与图片路径指南  mysql如何配置从库只读_mysql从库只读设置方法  聚水潭ERP后台管理系统登录 聚水潭ERP官方登录通道  sublime如何自定义文件类型图标_AFileIcon插件的主题切换与个性化配置  毒蘑菇VOLUMESHADER_BM官网首页登录入口 毒蘑菇VOLUMESHADER_BM官网首页登录入口说明  奥克斯空调不制热啥毛病_奥克斯空调不制热原因分析及解决技巧  win11如何运行chkdsk命令 Win11检查和修复磁盘逻辑错误教程【修复】  《sketchbook》选中部分图案移动方法  Python模块化编程:避免循环导入与共享函数的最佳实践  六级准考证号怎么查_四六级准考证查询入口官网  MySQL多重关联查询:利用别名高效获取同一表的多个关联字段  邮编号码查询app有哪些_邮编号码查询推荐app及使用体验  跨语言测试实践:使用Python Selenium测试现有J*a Web项目  《万兴喵影》导出视频方法  word页码灰色不能用如何解决  易车网官网直达入口 易车网在线登录入口  Retrofit根路径POST请求:@POST("/") 的应用与解析  顺丰快递在线查询系统 顺丰快递官方查单入口  TikTok笔记文字无法编辑如何解决 TikTok笔记文字编辑优化方法  steam缓存文件在哪儿_steam缓存文件的路径查找方法与结构说明  Flexbox布局实践:实现底部页脚与顶部粘性导航条的完美结合  Python csv 模块处理非字符串数据:列表写入 CSV 文件的机制解析  Lar*el Socialite单设备登录策略:实现用户唯一会话管理  猫眼app抢票快还是小程序快  智学网app怎么登录忘记密码_智学网app忘记密码找回与重新登录操作方法  在J*a里什么是行为抽象_抽象行为对代码复用的提升作用  在J*a中如何实现类的继承与方法重用_OOP继承方法重用技巧分享  全球各国上班时间表外贸邮件时间  《虎扑》取消评分记录方法  解决CSS容器溢出问题:使用calc()实现精确布局与边距控制  Python自动化抓取GBGB赛狗比赛结果:日期范围与赛道筛选教程  顺丰快递收费标准查询_如何查看顺丰最新收费价格  《健康大兴》注册方法介绍  不吃碳水化合物是健康减肥的好办法吗  win11自带录屏文件保存在哪里 Win11 Game Bar录制视频默认路径【分享】  PHP utf8_encode 字符编码转换疑难解析与最佳实践  如何用mysql实现客户反馈管理_mysql客户反馈数据库方法  《东方航空》添加乘机人方法  管理打开的编辑器:固定、分组和关闭技巧  msn官方入口2025登录 msn官网2025直达首页入口  如何在mysql中比较InnoDB和MyISAM区别  b站怎么设置动态仅粉丝可见_b站动态粉丝可见设置方法  Sublime怎么快速复制文件路径_Sublime右键菜单增强技巧  Win10显卡驱动安装失败怎么办 Win10使用DDU彻底卸载驱动【解决】  漫蛙漫画官方版直通入口 2025漫蛙漫画免注册访问说明 

 2025-10-06

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.