如何防止 Angular 中的多个订阅调用?

Posted

技术标签:

【中文标题】如何防止 Angular 中的多个订阅调用?【英文标题】:How do I prevent multiple subscription calls in Angular? 【发布时间】:2019-07-18 16:46:00 【问题描述】:

我有一个消息服务,用于在各种组件之间进行交互。当我点击Mine 按钮时,我只想触发一条消息。到目前为止,这有效。但是当我单击<> 按钮时,它会触发getMessage(),以便将值相加。但是当我点击Mine 时,我只想发送一个值。仅最后一个值。点击<>时如何防止触发getMessage()

当我点击<>时,它会在卡片之间从1切换到10。当我点击Mine时,它应该只取我所在的卡片并将信息从该块发送到另一个组件。但相反,当我单击 <> 时,getMessage() 被调用,它会将所有卡片加起来,直到我单击 Mine。我该如何防止呢?

遵循一些代码。我尽量保持紧凑:

消息服务.ts:

@Injectable( providedIn: 'root' )
export class MessageService 
  private subject = new Subject<any>();

  sendMessage(message: string) 
    this.subject.next( text: message );
  

  getMessage(): Observable<any> 
    console.log('Get Message Message Service');
    return this.subject.asObservable();
  

矿工卡组件:

  message: any;
  subscription: Subscription;

  constructor(private ref: ChangeDetectorRef, private emitTransactionService: EmitTransactionService,
              private messageService: MessageService) 
    this.subscription = this.messageService.getMessage().subscribe(message => 
      console.log('Constructor miner-card'); // gets called multiple times, depending on how often I click < and >. When I click 10 times on < or > it will call this subscription 10 times.
    );
  

当我点击&lt;&gt;时,这些函数被调用: 根据 minerCounter 的值,显示卡 1-10。

  precedingBlock() 
    this.minerCounter--;

    if (this.minerCounter < 1) 
      this.minerCounter = 10;
    
  

  nextBlock() 
    this.minerCounter++;

    if (this.minerCounter > 10) 
      this.minerCounter = 1;
    
  

带有&lt;&gt;按钮的卡片的外观:

Mine 按钮:

【问题讨论】:

take(1) 运算符将解决您在订阅中使用的问题 您还可以添加单击&lt;&gt; 时调用的函数吗? 【参考方案1】:

您应该始终unsubscribengOnDestroy 中的订阅。

  message: any;
  subscription: Subscription;

  constructor(private ref: ChangeDetectorRef, private emitTransactionService: EmitTransactionService,
              private messageService: MessageService) 
    this.subscription = this.messageService.getMessage().subscribe(message => 
      console.log('Constructor miner-card'); // gets called multiple times, depending on how often I click < and >. When I click 10 times on < or > it will call this subscription 10 times.
    );
  

ngOnDestroy() 
  this.subscription.unsubscribe();

【讨论】:

我也用过。如果我在 上点击 5 次,当我点击“我的”时它仍然会被调用 5 次 您是否尝试在 ngOnDestroy 上取消订阅 好的,谢谢。把它写在你的答案中,我会给你绿色的勾:)【参考方案2】:

在您的miner-card.component.ts 文件中使用take(1)。这只会从订阅中获取单个数据。

  message: any;
  subscription: Subscription;

  constructor(private ref: ChangeDetectorRef, private emitTransactionService: EmitTransactionService,
              private messageService: MessageService) 
    this.subscription = this.messageService.getMessage().pipe(take(1)).subscribe(message => 
      console.log('Constructor miner-card'); // gets called multiple times, depending on how often I click < and >. When I click 10 times on < or > it will call this subscription 10 times.
    );
  

希望这会有所帮助!

【讨论】:

我从 'rxjs/operators' 导入了 import take ;并且目前拥有与您相同的代码。但它说未解析的函数 take(1)。 如果您使用的是 rxjs 最新版本,那么您需要使用管道。检查更新的答案【参考方案3】:

检查您的订阅是否未定义。如果未定义,则仅订阅。

constructor(
private ref: ChangeDetectorRef,
private emitTransactionService: EmitTransactionService,
private messageService: MessageService
) 
if (!this.subscription) 
    this.subscription = this.messageService.getMessage().subscribe(message => 
      console.log('Constructor miner-card'); // gets called multiple times, depending on how often I click < and >. When I click 10 times on < or > it will call this subscription 10 times.
    );
  

【讨论】:

伙计,你或许应该考虑创建一个 StackBlitz。它将帮助我们更快地解决您的问题。

以上是关于如何防止 Angular 中的多个订阅调用?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2如何防止订阅触发,除非map返回的两个值中的任何一个发生了变化

如何在 Angular 和 RxJs 中管理多个顺序订阅方法?

如何在 API 调用完成之前防止 Angular 4.0 中的应用程序组件呈现

Angular2 Observable - 在继续之前等待多个函数调用

Angular - 竞争条件 - 一次多个订阅

我们是不是需要取消订阅 Angular 中的 http 调用? [复制]