问题
If I am ever working with rxjs
, I normally, in my component file, keep track of all of my subscriptions by pushing said subscriptions into a Subscription
array:
private subcriptions: Subscription[];
this.subscriptions.push(this.myObservableOne.subscribe(...));
this.subscriptions.push(this.myObservableTwo.subscribe(...));
public ngOnDestroy(): void {
this.subscriptions.forEach(s => s.unsubscribe());
}
Now, I am running into something that I thought was interesting. If I instead need to subscribe to an Observable from a service:
this.myService.myObservable.subscribe(...)
Who owns the subscription? Will my component own it, or will the service own it? In other words, will my service need to implement ngOnDestroy
to unsubscribe from that Observable?
I feel like doing: this.subscriptions.push(this.myService.myObservable.subscribe(...));
might work but I am not entirely sure.
回答1:
Calling .subscribe(...)
on an Observable returns a Subscription.
If you don't assign this subscription to a variable (or in your case push it to an array of subscriptions), you will lose reference to this subscription, hence you can't unsubscribe from it, which can cause memory leaks.
So your assumption of pushing it into array of subscriptions:
this.subscriptions.push(this.myService.myObservable.subscribe(...));
and unsubscribing in ngOnDestroy of your component is correct.
回答2:
Another option is to use takeWhile
or something similar with a flag such as the componentActive
flag below. Something like the code shown below.
This completes the subscription so you don't need to unsubscribe.
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Product } from '../product';
import { Observable } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
/* NgRx */
import { Store, select } from '@ngrx/store';
@Component({
selector: 'pm-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit, OnDestroy {
componentActive = true;
// Used to highlight the selected product in the list
selectedProduct: Product | null;
constructor(private store: Store<fromProduct.State>) { }
ngOnInit(): void {
// Subscribe here because it does not use an async pipe
this.store.pipe(
select(fromProduct.getCurrentProduct),
takeWhile(() => this.componentActive)
).subscribe(
currentProduct => this.selectedProduct = currentProduct
);
}
ngOnDestroy(): void {
this.componentActive = false;
}
}
来源:https://stackoverflow.com/questions/51504809/rxjs-observable-lifecycle