У меня есть приложение в angular 4, и я собрал почти все компоненты таким образом:
export class AreaProdottiComponent implements OnInit,OnDestroy {
subscription: ISubscription;
constructor(private someservice:Service){
this.subscription = someserviceObservable.subscribe(
res=>{
console.log('everything ok')
}
)
}
ngOnInit(){
this.someservice.fn()
}
ngOnDestroy(){
this.subscription.unsubscribe()
}
}
Эти компоненты взаимодействуют с сервисами, построенными почти таким образом:
export class Service(){
someservicesubj=Subject<any>();
someserviceObservable=someservicesubj.asObservable();
fn(){
doCall.subscribe(
res=>{
this.someservicesubj.next();
}
)
}
doCall()Observable<any>{
//some http call is here
}
}
Поэтому, когда создаются такие компоненты, они вызывают автоматический HTTP-метод из служб, и все вроде работает, но если я перехожу к приложению и возвращаюсь к тому же компоненту во второй раз, количество вызовов, которые совершаются, как только компонент создан дублирован, метод fn вызывается 2 раза. Это поведение усиливается каждый раз, когда я уничтожаю и воссоздаю компонент.
Примере:
Открывая компонент в консоли, я читаю «все в порядке», выхожу и возвращаюсь, я прочитаю «все в порядке» 3 раза, старый плюс 2 других.
Я думаю, что упускаю что-то в стратегии навигации или в построении сервиса, но я действительно не могу найти решение.
Обновить
Я пробовал, как предложил @trichetriche, но это все еще не работает. я использовал ISubscription вместо этого, это возможная проблема?
Обновить
@trichetriche был прав, но у меня была услуга, вызванная другим подписчиком, поэтому я пропустил тот факт, что это была первая услуга, подписка на которую была отменена.
2 ответа
Это потому, что подписки нужно закрывать, когда вы их открываете. И вы их не закрываете.
Однако я не буду комментировать неудачу создания тем для HTTP-вызовов.
export class AreaProdottiComponent implements OnInit, OnDestroy {
subscription: Subscription;
constructor(private someservice:Service){
this.subscription = someserviceObservable.subscribe(res => console.log('everything ok'));
}
ngOnInit(){
this.someservice.fn()
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Если вы хотите автоматически отказаться от подписки, вы можете использовать для этого декоратор.
export const randomString = () => Math.random().toString(36).slice(-8);
export function AutoUnsubscribe(blacklist = []) {
return function (constructor) {
const original = constructor.prototype.ngOnDestroy;
constructor.prototype.ngOnDestroy = function () {
// tslint:disable-next-line:forin
for (const prop in this) {
const property = this[prop];
if (!blacklist.includes(prop)) {
if (property && (typeof property.unsubscribe === 'function')) {
property.unsubscribe();
// console.log(prop + ' unsubscribed');
}
}
}
if (original && typeof original === 'function') { original.apply(this, arguments); }
};
};
}
Теперь ваш компонент будет выглядеть так
@AutoUnsubscribe()
export class AreaProdottiComponent implements OnInit, OnDestroy {
subscription: Subscription;
constructor(private someservice:Service){
this[randomString()] = someserviceObservable.subscribe(res => console.log('everything ok'));
}
ngOnInit(){
this.someservice.fn()
}
}
Причина в том, что вы никогда не отказываетесь от подписки, которую создаете в конструкторе компонентов. Каждый раз, когда создается экземпляр компонента, открывается новая подписка, и поэтому журналы увеличиваются на единицу при каждом переходе к этому компоненту.
Если вы хотите предотвратить такое поведение, вам следует сохранить подписку и закрыть ее с помощью метода ngOnDestroy
:
export class AreaProdottiComponent implements OnInit, OnDestroy {
private subscription: Subscription;
constructor(private someservice:Service){
this.subscription = someserviceObservable.subscribe(
res=>{
console.log('everything ok')
}
)
}
ngOnInit(){
this.someservice.fn()
}
public ngOnDestroy(): void {
if (this.subscription) this.subscription.unsubscribe();
}
}
Похожие вопросы
Новые вопросы
angular
Вопросы по Angular (не путать с AngularJS), веб-фреймворку от Google. Используйте этот тег для угловых вопросов, которые не относятся к конкретной версии. Для более старой веб-платформы AngularJS (1.x) используйте тег angularjs.