Я видел, что уже есть рабочие ответы, но я думаю, что вам лучше всего написать свой собственный оператор rx js для этого варианта использования. Это приводит к чистому решению, и ваша функция pipe
проясняет ваши намерения.
Для этого нам нужно использовать defer
наблюдаемый :
function tapSkipFirst<T>(fn: Function): OperatorFunction<T, T> {
return function(source: Observable<any>) {
return defer(() => {
let skip = true;
return source.pipe(
tap((v?:any) => {
if (!skip) {
fn(v);
}
skip = false;
})
);
});
};
}
Мы используем переменную skip
, чтобы решить, запустить ли функцию побочного эффекта или нет. В конце первого прогона мы переключаем skip
на false и, следовательно, запускаем функцию побочного эффекта для всех последующих прогонов. Нам нужно использовать наблюдаемую здесь defer
, потому что код внутри defer
вызывается только при подписке, а не при создании. Это важно, потому что в противном случае все подписки будут иметь одну и ту же переменную skip
.
И теперь вы можете легко использовать новый пользовательский оператор, например:
this.userChangeSubscription = this.userStateService.userState$
.pipe(
map(userState => userState.prop),
tapSkipFirst(() => this.sideEffect())
)
.subscribe();