Rx JS ведет себя не так, как ожидалось - PullRequest
2 голосов
/ 24 апреля 2020

Я работаю над приложением Angular 8, используя Rx JS 6. Я думал, что у меня все хорошо с Rx JS, но сегодня я столкнулся с чем-то, что заставляет меня думать, что у меня есть фундаментальное недопонимание того, как это работает.

У меня есть следующая подписка:

this.nudgePauseConnectivity$.pipe(
    tap(() => console.log(1)),
    withLatestFrom(this.hotspotPausedState$()),
    tap(() => console.log(2)),
    filter(([nudgePause, connectionPaused]) => connectionPaused === enums.HotspotPausedStateEnum.FALSE),
    tap(() => console.log(3)),
    switchMapTo(this._store.pipe(select(this._hotspotSelectors.selectUsername))),
    tap(() => console.log(4)),
    switchMap(username =>
        this._cabinApiV2Service.subscriberService.getRemainingConnectivityAllowance(username)
    ),
    tap(() => console.log(5)),
    map(remainingConnectivityAllowance => SubscriberConnectivityAllowanceTransformer.transform(
        remainingConnectivityAllowance
    ))
).subscribe(() => {/* Do something */});

nudgePauseConnectivity$ - это тема, которую я использую для выполнения тела наблюдаемого, например:

pauseConnectivity() {
    this.nudgePauseConnectivity$.next({});
}

this._hotspotSelectors.selectUsername - это селектор NgRx, который, если вы не использовали NgRx в наблюдаемой, которая возвращает значения из хранилища.

Моя проблема заключается в следующем: я думал, что выражение выполнится один раз для каждого значения, полученного из this.nudgePauseConnectivity$. Я бы ожидал увидеть в консоли:

1

2

3

4

5

Однако, похоже, что даже если this.nudgePauseConnectivity$ не выдает значение, выполнение выражения начинается, если this._store.pipe(select(this._hotspotSelectors.selectUsername)) выдает значение, поэтому я вижу такой вывод в консоли:

1

2

3

4

5

4

5

Я полностью смущен этим! Я не хочу, чтобы выражение когда-либо начинало выполняться в середине: я бы хотел, чтобы выражение выполнялось только в том случае, если this.nudgePauseConnectivity$ выдает значение, независимо от значений любых выражений в switchMap s или других наблюдаемых операторах высокого порядка позже в цепочке.

Как мне этого добиться?

1 Ответ

2 голосов
/ 24 апреля 2020

switchMap не отменяет подписку после первого выпуска. Ты должен сделать это. Мы обычно забываем об этом, потому что большую часть времени мы имеем дело с 1 наблюдаемым выбросом, таким как http-клиент. Поскольку у вас есть поток, который живет, пока работает ваше приложение, вместо:

switchMapTo(this._store.pipe(select(this._hotspotSelectors.selectUsername))),

вы можете сделать (до не прервать все цепочки из nudgePauseConnectivity$ - это ограничит только выбросы из switchMap в одну эмиссию, но при этом подписка будет nudgePauseConnectivity$ активна):

switchMap(() => this._store.pipe(
 select(this._hotspotSelectors.selectUsername), 
 take(1)
)

Или просто добавьте take(1) в цепочку после switchMapTo, если хотите чтобы прервать все выбросы после первого (это отменит подписку на nudgePauseConnectivity$ после 1-го выброса):

...
switchMapTo(this._store.pipe(select(this._hotspotSelectors.selectUsername))),
take(1),
...

Стоит взглянуть на другие части вашего кода, чтобы проверить, ' правильно отписаться от форм всех наблюдаемых вами (даже от angular форм).

...