是否可以在不手动存储的情况下获取所有“有效”订阅?
我想unsubscribe
所有“有效”订阅,并且不希望在数组或变量中引用它们。
答案 0 :(得分:7)
我取决于您使用的是主题还是观察者,但可能无法“自动”执行此操作。
我认为你不能拥有“订阅的Observable”这样的东西,因为你要么存储Observable,要么订阅:
const source = Observable.of(...)
.map(...);
const subscription = source
.subscribe();
此处source
代表一个Observable,subscription
代表一个订阅。
请注意,您可以拥有一个存储多个其他订阅的Subscription
实例:
const subscriptions = new Subscription();
const sub1 = Observable...subscribe();
const sub2 = Observable...subscribe();
const sub3 = Observable...subscribe();
subscriptions.add(sub1).add(sub2).add(sub3);
// Then unsubscribe all of them with a single
subscriptions.unsubscribe();
如果您使用的是主题,则他们自己拥有unsubscribe
方法,请参阅https://github.com/ReactiveX/rxjs/blob/master/src/Subject.ts#L96。
但请注意,这会使主题“停止”,有关详细信息,请参阅https://medium.com/@martin.sikora/rxjs-subjects-and-their-internal-state-7cfdee905156
答案 1 :(得分:4)
其中一种选择是将takeUntil与Subject结合使用以停止所有(可观察)订阅。
terminator$: Subject<boolean> = new Subject();
Observable.timer(1000)
.do(i => console.log(`timer 1: ${i}`))
.takeUntil(terminator$)
.subscribe();
Observable.timer(5000)
.do(i => console.log(`timer 2: ${i}`))
.takeUntil(terminator$)
.subscribe();
const stopSubscriptions = () => terminator$.next(true);
答案 2 :(得分:2)
我认为基本问题是Observable(除了Subject和衍生物)没有保留对它的观察者的引用。
如果没有内置引用,则需要以某种形式从外部处理它们。
我认为你能做到的最好的事情是创建一个可重用的订阅'覆盖'来包装机制,虽然我怀疑这是值得的。
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
const subscribeAndGuard = function(component, fnData, fnError = null, fnComplete = null) {
// Define the subscription
const sub: Subscription = this.subscribe(fnData, fnError, fnComplete);
// Wrap component's onDestroy
if (!component.ngOnDestroy) {
throw new Error('To use subscribeAndGuard, the component must implement ngOnDestroy');
}
const saved_OnDestroy = component.ngOnDestroy;
component.ngOnDestroy = () => {
console.log('subscribeAndGuard.onDestroy');
sub.unsubscribe();
// Note: need to put original back in place
// otherwise 'this' is undefined in component.ngOnDestroy
component.ngOnDestroy = saved_OnDestroy;
component.ngOnDestroy();
};
return sub;
};
// Create an Observable extension
Observable.prototype.subscribeAndGuard = subscribeAndGuard;
// Ref: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
declare module 'rxjs/Observable' {
interface Observable<T> {
subscribeAndGuard: typeof subscribeAndGuard;
}
}
参考此问题Angular/RxJs When should I unsubscribe from Subscription
答案 3 :(得分:1)
您可以只存储一个订阅,然后添加到其中。
private _subscriptions = new Subscription(); // yes you can do this!
然后添加到它
_subscriptions.add(
this.layoutManager.width$.subscribe((w) => {
// any nested subscriptions can also use this mechanism
_subscriptions.add(...);
});
然后在ngOnDestroy()
中,您只需呼叫_subscriptions.unsubscribe();
。
我一直在尝试做一个“聪明”的方法来做到这一点,但是坦率地说,我对它进行了过多的设计(包括日志记录),这是我遇到的最简单的方法。
答案 4 :(得分:1)
是的。如果您使用的是.observers
的{{1}}对象,只需调用Subject
属性。
希望这会有所帮助。
答案 5 :(得分:0)
最简单的方法是使用 ngx-auto-unsubscribe 。 使用此装饰器,您不应放置unsubscribe(),这是自动完成的。
要使用此功能,只需声明 onDestroy ,则无需在其中添加任何内容。
它非常易于使用,我鼓励您使用它。
答案 6 :(得分:0)
您可以继承实现OnDestroy接口的Base组件,并保留一个数组来存储所有的Subscription,最后销毁后,您可以找到带有instanceof Subscription的对象,然后全部取消订阅。让我写下面的代码。
export class BaseComponent implements OnInit, OnDestroy {
subscriptions: Subscription[] = [];
ngOnInit(): void {
}
ngOnDestroy(): void {
console.log('OnDestory - Baselass');
this.subscribers.forEach(sub => {
sub.unsubscribe();
console.log('Unsub');
})
}
addObserver(subscription: Subscription) {
this.subscribers.push(subscription);
}
}
export class SomeComponent extends BaseComponent implements OnInit, OnDestroy {
constructor(private someService: SomeService) {
super();
}
ngOnInit(): void {
super.ngOnInit();
}
ngOnDestroy(): void {
super.ngOnDestroy()
}
private initObservers() {
super.addObserver(this.someService.someObservable$.subscribe(res => {
}));
}
}
就是这样,您现在无需担心手动退订SubComponent的麻烦,BaseComponent会解决这个问题。
重要点: 必须将订阅传递给超类,这样才能保留列表并取消订阅组件销毁生命周期事件中的所有订阅。
super.addObserver(this.someService.someObservable$.subscribe(res => {
}));
谢谢!