首页 > 其他分享 >关于 Angular 应用开发里 Subject 和 BehaviorSubject 的用法一例

关于 Angular 应用开发里 Subject 和 BehaviorSubject 的用法一例

时间:2023-09-01 19:01:18浏览次数:45  
标签:订阅 BehaviorSubject import message MessageCenterService Angular Subject

笔者一直在 SAP 中国研究院从事 Commerce Cloud 这款 Angular 应用的开发,最近工作中修复了一个 bug.

在 Spartacus UI 上点击 Create 按钮之后:

维护 User 的明细数据,然后点击 Save 按钮:

点击之后,我们期望的结果是收到一条 用户成功创建的提示消息,并且页面自动导航回到点击 Create 按钮的页面。但 bug 修复之前,并没有成功创建的提示消息。

我们在 Github 这个 PR里修复了该问题。在解决方案里使用到了 Rxjs 的 Subject,我也顺带了解了 Subject 和 BehaviorSubject 的区别,本文将我的学习记录如下。

在 Angular 开发中,RxJS 是一个非常重要的库,它提供了强大的响应式编程工具,用于处理异步操作和数据流。Subject 是 RxJS 中的一个关键工具,它是一种特殊类型的 Observable,同时也可以被用于触发和监听事件,是实现事件总线的一种方式。BehaviorSubject 则是 Subject 的一个变种,它在 Subject 的基础上增加了初始值和记忆功能。

Subject 的特点和用法:

Subject 是一个多播的 Observable,它既是观察者也是可观察对象。这意味着我们可以通过 subscribe 方法订阅它,也可以通过 next 方法向它发送新值。Subject 会将这些值广播给所有订阅者。它通常用于实现事件总线、广播事件、多播数据流等场景。不过需要注意,Subject 在新的订阅者订阅时,不会向其发送之前发送的值。

BehaviorSubject 的特点和用法:

BehaviorSubject 继承自 Subject,在 Subject 的基础上增加了初始值和记忆功能。这意味着在 BehaviorSubject 被订阅时,它会发送其当前的值给订阅者。而当新的值通过 next 方法发送时,它会广播给所有订阅者,也会被记忆为新的当前值,以供新的订阅者使用。因此,BehaviorSubject 适用于需要初始值和对新订阅者广播最新值的情况。

现在,让我们通过一个详细的示例来说明 SubjectBehaviorSubject 的用法和区别。

示例场景:

假设我们正在开发一个实时聊天应用,我们需要一个消息中心来接收和分发聊天消息。我们可以使用 SubjectBehaviorSubject 来实现这个消息中心。让我们分别考虑这两种实现方式。

使用 Subject 实现消息中心:

首先,我们定义一个 MessageCenterService,其中包含一个 Subject 用于接收和分发消息:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class MessageCenterService {
  private messageSubject = new Subject<string>();

  sendMessage(message: string): void {
    this.messageSubject.next(message);
  }

  getMessage(): Subject<string> {
    return this.messageSubject;
  }
}

在聊天界面组件中,我们订阅消息中心的 Subject 来接收和显示聊天消息:

import { Component, OnDestroy } from '@angular/core';
import { MessageCenterService } from './message-center.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-chat',
  template: `
    <div *ngFor="let message of messages">{{ message }}</div>
  `
})
export class ChatComponent implements OnDestroy {
  messages: string[] = [];
  subscription: Subscription;

  constructor(private messageCenter: MessageCenterService) {
    this.subscription = this.messageCenter.getMessage().subscribe(message => {
      this.messages.push(message);
    });
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

使用 BehaviorSubject 实现消息中心:

现在,我们将 Subject 替换为 BehaviorSubject 来实现带有记忆功能的消息中心:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class MessageCenterService {
  private messageSubject = new BehaviorSubject<string>('Welcome to the chat');

  sendMessage(message: string): void {
    this.messageSubject.next(message);
  }

  getMessage(): BehaviorSubject<string> {
    return this.messageSubject;
  }
}

同样,我们在聊天界面组件中订阅消息中心的 BehaviorSubject 来接收和显示聊天消息:

import { Component, OnDestroy } from '@angular/core';
import { MessageCenterService } from './message-center.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-chat',
  template: `
    <div *ngFor="let message of messages">{{ message }}</div>
  `
})
export class ChatComponent implements OnDestroy {
  messages: string[] = [];
  subscription: Subscription;

  constructor(private messageCenter: MessageCenterService) {
    this.subscription = this.messageCenter.getMessage().subscribe(message => {
      this.messages.push(message);
    });
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

总结:

SubjectBehaviorSubject 都是 RxJS 中用于处理异步事件和数据流的强大工具。Subject 用于实现事件总线和多播数据流,而 BehaviorSubjectSubject 的基础上增加了初始值和记忆功能。在实际开发中,根据具体的需求,我们可以选择合适的工具来实现不同的功能。

标签:订阅,BehaviorSubject,import,message,MessageCenterService,Angular,Subject
From: https://blog.51cto.com/jerrywangsap/7325528

相关文章

  • 【Angular】 在组件内使用生命周期钩子函数如 OnDestroy 时,必须先 implements 么?
    不是必须,就算不implements,它也能被成功识别为生命周期钩子函数。但是最佳实践建议加入implements,可以增加钩子函数的数据类型检查,以及阻止某些因为未加入implements导致的错误。参考:AngularLifecycleInterfaceOnChangesshouldbeimplementedformethodngOnChanges......
  • 【Angular】Angular的Service什么时候被销毁?
    当ServiceA被声明在Moudule里时,模块里所有组件、管道、指令拥有同一个ServiceA的实例,当第一个需要注入该ServiceA的组件、管道、指令实例化A后,后面再需要注入ServiceA时,用的是同一个实例。当Moudle被销毁(通常是该模块的页面被卸载)后,ServiceA同步被销毁。当ServiceA被声明......
  • 【Angular】如何将自定义组件绑定为FormControl?
    参考资料:简单Demo:AngularFormcontrolenameCustomComponent关键实现说明:ControlValueAccessor:CustomFormComponentsinAngularAngular自定义表单控件(中文)关于muti:true的说明......
  • Angular:表单设置动态校验规则(ngZorro示例)
    背景有时我们需要根据不同的条件,决定表单控件是否是必填的。代码示例HTML文件<formnz-form[formGroup]="validateForm"(ngSubmit)="submitForm()"><nz-form-item><nz-form-label[nzSpan]="4"nzRequirednzFor="name">Name</nz-f......
  • 如何创建一个数据交互的Angular应用程序?这个工具不要错过!(一)
    当我们构建带有数据的应用程序时,需要为客户提供排序、分组、过滤和聚合数据等选项,以便与之交互。我们可以通过多种途径实现这一目标:使用内置的Array对象——它提供了过滤器、排序方法和reduce等用于分组和聚合的功能。使用KendoUIforAngular强大的数据查询功能——它提供了......
  • 浅谈Angular模板指令:ng-template和ng-container的用法
    本篇文章带大家简单了解一下Angular模板的ng-template和ng-container指令,介绍一下ng-template和ng-container指令使用方法。ng-template指令简介ng-template是一个Angular结构型指令,用来渲染HTML。它永远不会直接显示出来。事实上,在渲染视图之前,Angular会把ng-template......
  • angular初识
    电脑环境已安装node和npm,其中node是通过nvm管理的,参考:https://www.cnblogs.com/PrintY/p/16892116.html1、安装脚手架npminstall-gangular-cli测试安装结果ng-v运行项目修改package.json(非必须)//加上--open,启动项目打开浏览器"start":"ngserve--open",vscode......
  • Angular 应用启用 PWA 特性的 Angular CLI 命令行
    ngadd@angular/pwa--project<project-name>这条命令在AngularCLI中,是用于将一个标准的Angular应用程序转化为一个渐进式网页应用(PWA,ProgressiveWebApp)的命令。首先,我们需要理解PWA是什么。PWA是一种可以提供类似于原生应用体验的网页应用。它可以在离线时工作,可被......
  • 在Angular项目中如何读取json文件呢?
    直接进入主题,我们的最终目得是要读取文件,那么首先我们需要先创建文件,第一步:创建我们今天所需要在assets创建需要读取的文件Message.json,如下:[{"id":"E0001","msg":"{0}の取得に失敗しました。"},{"id":"E0002",&quo......
  • 关于Angular路由中CanActivateChild钩子的用法
    CanActivateChild和CanActivate的用法如出一辙,使用对象可能有所不同,例如说CanActivate一般的使用对象要么是兄弟平级关系,要么就是嵌套在CanActivateChild父级下的子路由。具体使用实例:constroutes:Routes=[{path:'home',component:HomeComponent,canActivateChild:[......