在我的Angular 2应用程序中,我有许多可观察和订阅。 当然,当我离开页面时,我应该取消订阅,但是我试图找出是否有可能获得有效订阅的数量。 仅用于调试信息或忘记取消订阅时。
rxjs中是否有此类信息?
答案 0 :(得分:3)
可能有点晚了,但是您可以利用rxjs-spy
的帮助。
此解决方案与建议的解决方案等效,并且在我看来,维护性更好。
通常,我会在main.ts中全局启用它,将其作为一种即发即弃策略。您只需要:
import { create } from 'rxjs-spy';
`
if (environment.production) {
enableProdMode();
}
else {
//we enable RXjs Spy on non production bulds only
const spy = create();
// we call show for two purposes: first is to log to the console an empty snapshot so we can see that everything is working as expected, then to suppress unused variable usage (the latter is a convention on mine)
spy.show();
}
`
`
import { tag } from 'rxjs-spy/operators';
...
// This is a sample method which asks for a "Product" entity. Product and this.http is omitted as the focus is on tagging the observable
public getProductById(productId: number): Observable<Product> {
let params = new HttpParams()
.append('productId', productId.toString())
;
// we tag the returned observable with the name 'getProductById' (this is a convention on mine, you can choose whatsoever name)
return this.http.get<Product>(this.baseUrl + "api/product", { params: params }).pipe(tag("getProductById"));
}
`
rxSpy.show()
即可获取当前快照您可以使用其他命令。非常详细的教程是Debugging with rxjs Spy。
(如果有人阅读此答案后能够解决格式问题,我感到很高兴,因为我无法在列表中正确找到格式)
答案 1 :(得分:2)
在您的情况下,您可以通过refCounting充分利用RxJS主题。您可以为Subject提供可观察的源,并让refCount管理其订阅。 如果没有观察者收听,refCount将取消订阅您的源可观察对象。另一方面,如果观察者计数为0并且观察者订阅了它,则会创建新的source observable实例。
主体将充当观察者和观察源之间的代理,并管理订阅和取消订阅。本质上它是如何工作的是当你的第一个观察者订阅你的主题时,主题依次订阅你的源可观察量(refCount从0变为1)。主体允许多个观察者监听单播源可观察性使其成为多播。当观察者开始取消订阅并且refCount再次降至0时,主体本身将取消订阅源可观察数据。
在代码中可以更好地理解:
const {
Observable
} = Rx;
let sourceObservable = Observable
.create((observer) => {
let count = 0;
let interval = setInterval(() => {
observer.next(count++)
}, 700);
setTimeout(() => {
clearInterval(interval);
observer.complete();
}, 5500);
return () => {
clearInterval(interval);
console.log('######## Source observable unsubscribed');
}
})
.do((x) => console.log('#### Source emits: ' + x));
let subject = sourceObservable
.share()
//.do((x) => console.log('#### Subject emits: ' + x))
;
let pageOneObserver;
let pageTwoObserver;
let pageThreeObserver;
setTimeout(() => {
console.log('pageOneObserver will subscribe');
pageOneObserver = subject.subscribe({
next: (x) => {
console.log('pageOneObserver gets: ' + x);
},
complete: () => {
console.log('pageOneObserver: complete');
}
});
}, 1000);
setTimeout(() => {
console.log('pageTwoObserver will subscribe');
pageTwoObserver = subject.subscribe({
next: (x) => {
console.log('pageTwoObserver gets: ' + x);
},
complete: () => {
console.log('pageTwoObserver: complete');
}
});
}, 4000);
setTimeout(() => {
console.log('pageOneObserver will unsubscribe');
pageOneObserver.unsubscribe();
}, 7000);
setTimeout(() => {
console.log('pageTwoObserver will unsubscribe');
pageTwoObserver.unsubscribe();
}, 10000);
setTimeout(() => {
console.log('pageThreeObserver will subscribe');
pageThreeObserver = subject.subscribe({
next: (x) => {
console.log('pageThreeObserver gets: ' + x);
},
complete: () => {
console.log('pageThreeObserver: complete');
}
});
}, 13000);
setTimeout(() => {
console.log('pageThreeObserver will unsubscribe');
pageThreeObserver.unsubscribe();
}, 16000);
&#13;
<script src="https://unpkg.com/rxjs@5.1.1/bundles/Rx.min.js"></script>
&#13;
有一些创作主题的简写方法。例如:
sourceObservable.share();
// is the same as
sourceObservable.publish().refCount();
sourceObservable.publish().refCount();
// is the same as
sourceObservable.multicast(new Rx.Subject()).refCount();
sourceObservable.publishReplay().refCount();
// is the same as
sourceObservable.multicast(new Rx.ReplaySubject(1)).refCount();
sourceObservable.publishBehavior().refCount();
// is the same as
sourceObservable.multicast(new Rx.BehaviorSubject(0)).refCount();
sourceObservable.publishLast().refCount();
// is the same as
sourceObservable.multicast(new Rx.AsyncSubject()).refCount();
sourceObservable.share();
还内置了主题工厂,这意味着当源observable在某些时候完成时,我们必须创建一个sourceObservable的新实例,但只能使用你的主题的新实例来完成选择。使用下面的其他可用主题,我们必须明确地将工厂函数返回给多播运算符。
如果您想使用除Rx.Subject()之外的其他主题类型并且想要使您的可观察订阅真正可重用,您必须使用主题工厂(这只是一个返回您喜欢的任何主题的新实例的函数)使用),如下图所示:
const {
Observable
} = Rx;
let sourceObservable = Observable
.create((observer) => {
let count = 0;
let interval = setInterval(() => {
observer.next(count++)
}, 700);
setTimeout(() => {
clearInterval(interval);
observer.complete();
}, 5500);
return () => {
clearInterval(interval);
console.log('######## Source observable unsubscribed');
}
})
.do((x) => console.log('#### Source emits: ' + x));
/* You could return whatever subject instance you like here */
let subjectFactory = () => new Rx.ReplaySubject(1);
let subject = sourceObservable
.multicast(subjectFactory)
.refCount();
//.do((x) => console.log('#### Subject emits: ' + x))
;
let pageOneObserver;
let pageTwoObserver;
let pageThreeObserver;
setTimeout(() => {
console.log('pageOneObserver will subscribe');
pageOneObserver = subject.subscribe({
next: (x) => {
console.log('pageOneObserver gets: ' + x);
},
complete: () => {
console.log('pageOneObserver: complete');
}
});
}, 1000);
setTimeout(() => {
console.log('pageTwoObserver will subscribe');
pageTwoObserver = subject.subscribe({
next: (x) => {
console.log('pageTwoObserver gets: ' + x);
},
complete: () => {
console.log('pageTwoObserver: complete');
}
});
}, 4000);
setTimeout(() => {
console.log('pageOneObserver will unsubscribe');
pageOneObserver.unsubscribe();
}, 7000);
setTimeout(() => {
console.log('pageTwoObserver will unsubscribe');
pageTwoObserver.unsubscribe();
}, 10000);
setTimeout(() => {
console.log('pageThreeObserver will subscribe');
pageThreeObserver = subject.subscribe({
next: (x) => {
console.log('pageThreeObserver gets: ' + x);
},
complete: () => {
console.log('pageThreeObserver: complete');
}
});
}, 13000);
setTimeout(() => {
console.log('pageThreeObserver will unsubscribe');
pageThreeObserver.unsubscribe();
}, 16000);
&#13;
<script src="https://unpkg.com/rxjs@5.1.1/bundles/Rx.min.js"></script>
&#13;
如果还有不清楚的事情,请随时询问。
答案 2 :(得分:0)
以下效用函数可能会有所帮助...
function subscriberCount<T>(sourceObservable: Observable<T>, description: string) {
let counter = 0;
return Observable.create((subscriber: Subscriber<T>) => {
const subscription = sourceObservable.subscribe(subscriber);
counter++;
console.log(`${description} subscriptions: ${counter}`);
return () => {
subscription.unsubscribe();
counter--;
console.log(`${description} subscriptions: ${counter}`);
}
});
}
像这样使用:
const timer$ = subscriberCount(Observable.timer(1000), 'Timer');
每当订户数量发生变化时,控制台都会记录
答案 3 :(得分:-1)
在组件销毁后使用 this 操作取消订阅
示例:
ngOnInit() {
interval(1000)
.pipe(
untilComponentDestroyed(this) // <-- use the operator
)
.subscribe();
}