Угловая приватная тема rxjs + общедоступная наблюдаемая настройка - PullRequest
0 голосов
/ 02 ноября 2018

Я новичок в rxjs / observables. Они немного над моей головой, так что это может быть простой вопрос.

Я хочу иметь тему в сервисе, которая может часто вызываться для получения обновлений. Затем обновление может быть немедленно возвращено вызывающей стороне (если они ждут), но также отправлено любым подписчикам. Я бы хотел, чтобы тема была приватной, поэтому только служба может .next().

Последнее предостережение: когда что-то подписывается на наблюдаемое, я хотел бы получить текущее значение ОДИН РАЗ, а затем получать оповещения о любых обновлениях после этого. Моя попытка новичка ниже. Кажется, что в основном это работает, но подписка на страницу получает текущее значение один раз за вызов next() при первоначальной подписке. Таким образом, если getNewThings() вызывается 5 раз, подписка на страницу немедленно получит текущее значение темы 5 раз. Как я могу это исправить?

Услуги

@Injectable()
export class PretendService{
    private mySubject: BehaviorSubject<Thing[]> = new BehaviorSubject<Thing[]>(null);
    public readonly mySubjectObservable: Observable<Thing[]> = this.mySubject.asObservable();
    ...
    public getNewThings(): Promise<Thing[]>{
        let p = new Promise<Thing[]>((resolve, reject) => {

            //Do the work to get Thing[]s
            let theThings: Thing[] = [];
            mySubject.next(theThings);
            resolve(theThings);
        }

        return p;
    }
}

Страница

...
thingSubscription: Subscription;
constructor(private pretendService: PretendService){
    this.thingSubscription = this.pretendService.mySubjectObservable.subscribe((things)=>{
        //ISSUE HERE: 
        //This fires once per .next() with the current value on initial subscription
        console.log(`got some things [{things}]`);
    });
}
...
//Unsubscribe in destructor...etc...

UPDATE

Вот фрагмент стека, который показывает кое-что из этого. Нажатие на главную кнопку вызовет метод обновления несколько раз. Затем нажмите ссылку «Другая страница», чтобы активировать подписку. Обратите внимание, что в компоненте Page2 есть реализация OnDestroy, которую можно комментировать / не комментировать. Это было моей главной проблемой - я не уничтожал должным образом, поэтому собирал подписки. https://stackblitz.com/edit/angular-umk8qm?embed=1&file=src/app/page2.component.ts

1 Ответ

0 голосов
/ 02 ноября 2018

См. StackBlitz об обновлении. В моем случае я не реализовал OnDestroy должным образом, что заставило мое приложение накапливать подписки. Это выглядело так, как будто он получал 1 обновление за next() вызов на BehaviorSubject. Тем не менее, он получал только 1, но, поскольку создавалось много подписок, казалось, что 1 подписка получает несколько обновлений. Более полная реализация приведена ниже.

Страница

export class Page2Component implements OnDestroy
...
thingSubscription: Subscription;
constructor(private pretendService: PretendService){
    this.thingSubscription = this.pretendService.mySubjectObservable.subscribe((things)=>{
        console.log(`got some things [{things}]`);
    });
}
...
ngOnDestroy() {    
    //This should fire if things are destroying properly
    console.log('destroying!');
    this.thingSubscription && this.thingSubscription.unsubscribe();
}
....
...