如何防止 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.
);
当我点击<
和>
时,这些函数被调用:
根据 minerCounter 的值,显示卡 1-10。
precedingBlock()
this.minerCounter--;
if (this.minerCounter < 1)
this.minerCounter = 10;
nextBlock()
this.minerCounter++;
if (this.minerCounter > 10)
this.minerCounter = 1;
带有<
和>
按钮的卡片的外观:
Mine
按钮:
【问题讨论】:
take(1) 运算符将解决您在订阅中使用的问题 您还可以添加单击<
或>
时调用的函数吗?
【参考方案1】:
您应该始终unsubscribe
ngOnDestroy
中的订阅。
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 中的应用程序组件呈现