#angular #typescript #rxjs #ngrx
Вопрос:
У меня есть ситуация, в которой диалоговое окно может быть открыто, когда мы получаем обновление от BE через SSE, но закрыто, когда другое обновление изменяет предыдущее состояние.
Я создал вспомогательную функцию, которая вызывается изнутри effect
и принимает в качестве параметра ссылку на открытый диалог. Там я подписываюсь на обновление статуса устройства, и если условие выполнено, диалоговое окно закрывается, и селектор должен быть отписан. Но он также должен быть отменен, когда пользователь закрывает диалоговое окно вручную. Теперь полученный код кажется мне очень странным.
private closeOnStatusChange(dialog: MatDialogRef<ConfirmDialogComponent>): void {
this.store
.select(fromDevice.selectDeviceStatus)
.pipe(
map(({ deviceStatus }) => deviceStatus === DeviceStatus.INACTIVE || deviceStatus === DeviceStatus.FAILED),
takeWhile(shouldClose => !shouldClose), // if status is 'ok', observe but do not unsubscribe
takeUntil(dialog.afterClosed()), // unsubscribe when dialog is closed
filter(shouldClose => shouldClose), // status is 'fail', continue and close the dialog
tap(() => dialog.close())
)
.subscribe();
}
Честно говоря, я не могу понять, правильна ли эта цепочка или есть какие-то скрытые уловы. После краткого тестирования кажется, что это работает, но это просто кажется неправильным. Есть идеи, как с этим справиться, возможно, без использования вспомогательных переменных?
Ответ №1:
Попробуйте использовать take
— для этого требуется всего 1 событие и немедленно отпишитесь. Я дополнительно переключаю вас tap
на подписку (но вы можете оставить ее после take(1)
). Код из головы — не проверялся
.pipe(
map(({ deviceStatus }) => deviceStatus === DeviceStatus.INACTIVE || deviceStatus === DeviceStatus.FAILED),
takeWhile(shouldClose => !shouldClose), // if status is 'ok', observe but do not unsubscribe
takeUntil(dialog.afterClosed()), // unsubscribe when dialog is closed
filter(shouldClose => shouldClose), // status is 'fail', continue and close the dialog
take(1)
)
.subscribe(() => dialog.close())
Комментарии:
1. Если он используется после
filter
, означает ли это, что я могу избежатьtakeWhile
. Я никогда не был уверен в этом2. @dallows Я не совсем понимаю ваш (основной) вопрос, но вы спрашиваете об отписке после того, как все сделано — поэтому я даю ответ на эту часть вашего вопроса. Однако, если у вас есть два источника событий — может быть, будет лучше описать это явным образом как две отдельные наблюдаемые, отфильтровать их — и объединить, используя, например
merge
, и затемtake
…