Angular 事件订阅的潜在问题

Potential issue with subscription on event with Angular

在没有 Subscription 对象的情况下,在事件期间订阅服务(例如单击按钮)会带来问题吗?例如,这是我偶然发现的一个小片段:

usernames: string[];

...

public getFullName(userID: string)  {
    this.restApi.getFullName(userID).subscribe(response => {
        this.usernames.push(response);
    });
}

我想知道是否为每次调用该服务“添加”了订阅? (第一个调用添加一个订阅,推送一个项目,然后第二个调用添加另一个订阅到这个 Observable 并推送一个项目两次,依此类推)

更好的做法是在 OnInit() 方法中订阅每个服务,这样您只订阅一次而不会出现内存/性能问题?或者使用订阅对象来确保您的订阅在第二次调用时被“覆盖”?

您的订阅越少,您的应用就越有可能在没有任何内存问题的情况下运行。

上面的代码已经够危险了,因为您订阅了每个事件并且永远不会取消订阅。

换句话说,如果您需要在每次点击时都创建一个订阅,您可以支持它,但如果您只在初始化时创建一个订阅,则效率会更高。

我建议您阅读这篇文章:when-to-unsubscribe 还有这个:how-to-unsubscribe

#编辑

我真的很喜欢 @MoxxiManagarm 的另一个答案的代码,只留下我的两个词,因为我真的相信这篇文章很有帮助如果有人最终阅读了这个问题.

你的怀疑是对的。我为您的用例推荐 scan 运算符。

lastUserIdRequested: Subject<string> = new Subject();
usernames: string[];

ngOnInit() {
  this.lastUserIdRequested.pipe(
    concatMap(userId => this.restApi.getFullName(userId)),
    scan((acc, fullname) => [...acc, fullname], []),
  ).subscribe(fullnames => this.usernames = fullnames);
}

public getFullName(userId: string) {
  // this could be called directly from template without the getFullName method
  this.lastUserIdRequested.next(userId);
}

每次 getFullName 都会添加一个新订阅,所以是的;表演将因此受到影响。您可以像 MoxxiManagarm 所说的那样使用 scanner 或者您可以使用 takeWhile:

简化逻辑
public getFullName(userID: string)  {
    let isAlive = true;
    this.restApi.getFullName(userID).pipe(
    takeWhile(() => isAlive)
    ).subscribe(response => {
        isAlive = false;
        this.usernames.push(response);
    });
}

takeWhile 运算符关闭订阅并在达到特定条件时将其删除。