У меня есть метод, который возвращает Observable
subFoo(id): Observable<number> {
return new Observable<number>(observer => {
setTimeout(() => {
observer.next(id);
}, 1000);
});
}
теперь я подписал его три раза, а после 5 секунд отменил все:
const sub1 = subFoo(1).subscribe(result => console.log(result));
const sub2 = subFoo(2).subscribe(result => console.log(result));
const sub3 = subFoo(3).subscribe(result => console.log(result));
setTimeout(() => {
sub1.unsubscribe();
sub2.unsubscribe();
sub3.unsubscribe();
}, 5000);
я могу справиться с полным unsubscrite всех слушателей?
например. (в псевдокоде):
subFoo(id): Observable<number> {
return new Observable<number>(observer => {
// something like this
observer.onAllListenerAreUnsubscribed(() => {
console.log('All Listener Are Unsubscribed!');
});
setTimeout(() => {
observer.next(id);
}, 1000);
});
}
Демо-версия: https://stackblitz.com/edit/angular-ayl12r
Наблюдатель может знать о подписках на свои цепочки. Если вы хотите узнать, сколько раз кто-то подписался, вы можете считать это самостоятельно:
let subscriptions = 0;
subFoo(id): Observable<number> {
return new Observable<number>(observer => {
subscriptions++;
...
return (() => {
if (--subscriptions === 0) {
// do whatever...
}
...
})
})
})
Вы также можете собирать все подписки на стороне наблюдателя в одну подписку, а затем добавлять пользовательский обработчик при отмене подписки:
const subs = new Subscription();
subs.add(subFoo(1).subscribe(...));
subs.add(subFoo(2).subscribe(...));
subs.add(subFoo(3).subscribe(...));
subs.add(() => {
// do whatever...
});
subs.unsubscribe(); // Will unsubscribe all subscriptions and then call your custom method.
Завершив сразу все ваши наблюдаемые данные, вы уверены, что не получите утечки данных. Вы можете создать объект, который будет излучать, когда наблюдаемые должны прекратить излучать и использовать оператор takeUntil() на ваших наблюдаемых, например:
const completeSubscription: Subject<void> = new Subject();
const sub1 = subFoo(1)
.pipe(takeUntil(completeSubscription))
.subscribe(result => console.log(result));
const sub2 = subFoo(2)
.pipe(takeUntil(completeSubscription))
.subscribe(result => console.log(result));
const sub3 = subFoo(3)
.pipe(takeUntil(completeSubscription))
.subscribe(result => console.log(result));
setTimeout(() => {
completeSubscription.next();
completeSubscription.complete();
}, 5000);
вы можете отказаться от подписки на всех слушателей в одной строке, поэтому не нужно обрабатывать это событие
subscriptions.add(sub1).add(sub2).add(sub3);
// Then unsubscribe all of them with a single
subscriptions.unsubscribe();