【问题标题】:Angular 4, Observables, and "Cannot read property 'unsubscribe' of null"Angular 4、Observables 和“无法读取属性 'unsubscribe' of null”
【发布时间】:2018-05-31 06:49:27
【问题描述】:

我正在尝试使用 observables,但我收到一条错误消息,提示“无法读取属性 'unsubscribe' of null”。我想知道我应该在哪里调用我的取消订阅方法。我也想知道我的可观察设置是否错误。我有一个服务、一个组件和一个看起来像这样的 HTML 模板:

 // *** Service *** 
 private elements : Map<Category, string[]> = new Map<Category, string[]>();

 // I want to populate the map when the service is constructed
 constructor(private httpClient : HttpClient){
    for (enum in Category){
       if (!isNaN(enum as any)){
          this.httpClient.get<string[]>(someUrl + enum).subscibe(data => {
            this.elements.set(category, data);
          });
       }
    }
 }

 getElements(category: Category) : Observable<string[]> {
    return Observable.create(this.elements.get(category)); 
 }
 .
 .
 .
 // *** The component ***
 getCategoryList(category : Category) : Observable<string[]> {
   this.categoryService.getElements(category);
 }

 .
 .
 .
 // *** The template ****
 <div *ngFor="let element of getCategoryList('WARM_ELEMENTS') | async ">
    <div class="row">
       {{element}} 
    </div>
 </div>

我想我在某个地方需要一个取消订阅方法,或者 / 并且我的可观察设置有问题(我现在正在学习 Angular)。

【问题讨论】:

  • 通常你在 ngOnDestroy 生命周期钩子中取消订阅 Observable。 angular.io/api/core/OnDestroy
  • 所以我可以在组件的 ngOnDestroy 挂钩中取消订阅?我不明白在这种情况下如何退订?
  • .subscibe?这段代码甚至无法编译。请发布实际的编译代码,以及您得到的确切和完整的错误。但是为什么你将一个字符串数组包装到一个 Observable 中?重点是什么?为什么不直接返回字符串数组呢?你知道 Observable.create() 是一个函数,而不是一个字符串数组吗?同样,这不会编译。

标签: angular rxjs


【解决方案1】:

通常,您在使用HttpClient 时不需要取消订阅,如果您想确保无需订阅,您可以改为使用take(1)

 this.httpClient.get<string[]>(someUrl + enum).take(1).subscibe(data => {
    this.elements.set(category, data);
 });

如果您想真正让订阅始终有效(例如当您使用 firebase 时),您需要在 OnDestory 内取消订阅并将该订阅分配给一个变量以便您可以访问它,但 OnDestory 用于组件 不是为了服务其实也是为了服务。

无论如何,还有其他选择;使用takeWhile()takeUntil()

你可能需要类似的东西:

 private _keepAlive: boolean = true;

 constructor(private httpClient : HttpClient){
    for (enum in Category){
       if (!isNaN(enum as any)){
          this.httpClient.get<string[]>(someUrl + enum).takeWhile(() => this._keepAlive).subscibe(data => {
            this.elements.set(category, data);
          });
       }
    }
 }

 stopSubscription() : void { // this is just an option you can remove it
    this._keepAlive = false;
 }

 ngOnDestroy()
 {
    this._keepAlive = false;
 }

这并不是最理想的,但我希望至少能回答你的问题。

这里还有一个问题,答案应该对你有帮助:Angular/RxJs When should I unsubscribe from `Subscription`

【讨论】:

  • OnDestroy 也适用于服务,而不仅仅是组件。
  • 而且您的代码也会泄漏内存,因为您对整个循环使用单个订阅变量。它没有的唯一原因是因为(如你所说),HttpClient 完成了 observable。
  • @IngoBürk 感谢您提供的信息,并没有注意到循环 :) 我将编辑我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 2012-10-03
  • 2018-10-11
相关资源
最近更新 更多