RxJS iif 参数在不应该调用的时候被调用
RxJS iif arguments are called when shouldn't
我想使用 RxJS 中的 iif 实用程序有条件地分派一些操作。问题是即使测试函数 returns 为假,iif 的第二个参数也会被调用。这会引发错误并且应用程序会立即崩溃。我不熟悉 RxJS 的强大功能,所以我可能什么都不知道。如果重要的话,我正在使用 connected-react-router 包。
export const roomRouteEpic: Epic = (action$, state$) =>
动作$.ofType(LOCATION_CHANGE).pipe(
采摘('payload'),
mergeMap(有效载荷=>
iif(
() => {
console.log('NOT LOGGED');
return /^\/room\/\d+$/.test(payload.location.pathname); // 设置为 '/login'
},
合并(
点击(v => console.log('NOT LOGGED TOO')),
的(
// 立即评估以下状态值
状态$.value.rooms.list[payload.location.pathname.split('/')[1]]
? actions.rooms.initRoomEnter()
: actions.rooms.initRoomCreate(),
),
的(actions.global.setIsLoading(真)),
),
空的(),
),
),
);
如果你在observable创建中使用tap运算符(因为它returns无效),会导致如下错误
Error: You provided 'function tapOperatorFunction(source) {
return source.lift(new DoOperator(nextOrObserver, error, complete));
}' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
移除水龙头并将控制台放入 subscribe()。
我创建了一个 stackblitz demo。
好的,我自己找到了答案。我的解决方案是完全删除 iif 并仅依赖 mergeMap 中的三元运算符。这样它就不会在每个 'LOCATION_CHANGE' 之后进行评估,并且如果 regExp returns 为真。感谢您的关注。
export const roomRouteEpic: Epic = (action$, state$) =>
action$.ofType(LOCATION_CHANGE).pipe(
pluck<any, any>('payload'),
mergeMap(payload =>
/^\/room\/\d+$/.test(payload.location.pathname)
? of(
state$.value.rooms.list[payload.location.pathname.split('/')[2]]
? actions.rooms.initRoomEnter()
: actions.rooms.initRoomCreate(),
actions.global.setIsLoading(true),
)
: EMPTY,
),
);
有点晚了,不过我发现iif
的作用是不是执行一条路在另一个之上,而是订阅一个 Observable 或另一个。也就是说,它将执行获取每个 Observable 所需的所有代码路径。
从这个例子...
import { iif, of, pipe } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
const source$ = of('Hello');
const obsOne$ = (x) => {console.log(`${x} World`); return of('One')};
const obsTwo$ = (x) => {console.log(`${x}, Goodbye`); return of('Two')};
source$.pipe(
mergeMap(v =>
iif(
() => v === 'Hello',
obsOne$(v),
obsTwo$(v)
))
).subscribe(console.log);
你会得到以下输出
Hello World
Hello, Goodbye
One
这是因为,为了得到 obsOne$
它需要打印 Hello World
。 obsTwo$
也是如此(除了路径打印 Hello, Goodbye
)。
但是您会注意到它只打印 One
而不是 Two
。这是因为 iif
评估为 true
,因此订阅了 obsOne$
。
虽然你的三元组有效——我发现这篇文章解释了一种更受 RxJS 驱动的方式,可以很好地实现你想要的结果:https://rangle.io/blog/rxjs-where-is-the-if-else-operator/
我想使用 RxJS 中的 iif 实用程序有条件地分派一些操作。问题是即使测试函数 returns 为假,iif 的第二个参数也会被调用。这会引发错误并且应用程序会立即崩溃。我不熟悉 RxJS 的强大功能,所以我可能什么都不知道。如果重要的话,我正在使用 connected-react-router 包。
export const roomRouteEpic: Epic = (action$, state$) => 动作$.ofType(LOCATION_CHANGE).pipe( 采摘('payload'), mergeMap(有效载荷=> iif( () => { console.log('NOT LOGGED'); return /^\/room\/\d+$/.test(payload.location.pathname); // 设置为 '/login' }, 合并( 点击(v => console.log('NOT LOGGED TOO')), 的( // 立即评估以下状态值 状态$.value.rooms.list[payload.location.pathname.split('/')[1]] ? actions.rooms.initRoomEnter() : actions.rooms.initRoomCreate(), ), 的(actions.global.setIsLoading(真)), ), 空的(), ), ), );
如果你在observable创建中使用tap运算符(因为它returns无效),会导致如下错误
Error: You provided 'function tapOperatorFunction(source) {
return source.lift(new DoOperator(nextOrObserver, error, complete));
}' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
移除水龙头并将控制台放入 subscribe()。
我创建了一个 stackblitz demo。
好的,我自己找到了答案。我的解决方案是完全删除 iif 并仅依赖 mergeMap 中的三元运算符。这样它就不会在每个 'LOCATION_CHANGE' 之后进行评估,并且如果 regExp returns 为真。感谢您的关注。
export const roomRouteEpic: Epic = (action$, state$) =>
action$.ofType(LOCATION_CHANGE).pipe(
pluck<any, any>('payload'),
mergeMap(payload =>
/^\/room\/\d+$/.test(payload.location.pathname)
? of(
state$.value.rooms.list[payload.location.pathname.split('/')[2]]
? actions.rooms.initRoomEnter()
: actions.rooms.initRoomCreate(),
actions.global.setIsLoading(true),
)
: EMPTY,
),
);
有点晚了,不过我发现iif
的作用是不是执行一条路在另一个之上,而是订阅一个 Observable 或另一个。也就是说,它将执行获取每个 Observable 所需的所有代码路径。
从这个例子...
import { iif, of, pipe } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
const source$ = of('Hello');
const obsOne$ = (x) => {console.log(`${x} World`); return of('One')};
const obsTwo$ = (x) => {console.log(`${x}, Goodbye`); return of('Two')};
source$.pipe(
mergeMap(v =>
iif(
() => v === 'Hello',
obsOne$(v),
obsTwo$(v)
))
).subscribe(console.log);
你会得到以下输出
Hello World
Hello, Goodbye
One
这是因为,为了得到 obsOne$
它需要打印 Hello World
。 obsTwo$
也是如此(除了路径打印 Hello, Goodbye
)。
但是您会注意到它只打印 One
而不是 Two
。这是因为 iif
评估为 true
,因此订阅了 obsOne$
。
虽然你的三元组有效——我发现这篇文章解释了一种更受 RxJS 驱动的方式,可以很好地实现你想要的结果:https://rangle.io/blog/rxjs-where-is-the-if-else-operator/