RxJS iif参数在';T

RxJS iif参数在';T,rxjs,redux-observable,Rxjs,Redux Observable,我想使用RxJS中的iif实用程序有条件地分派一些操作。问题是,即使测试函数返回false,也会调用iif的第二个参数。这会引发错误,应用程序会立即崩溃。我对RxJS的力量还不熟悉,所以我可能不知道什么。如果有必要的话,我正在使用连接的路由器包 export const roomRouteEpic: Epic = (action$, state$) => action$.ofType(LOCATION_CHANGE).pipe( pluck('payload'), merge

我想使用RxJS中的iif实用程序有条件地分派一些操作。问题是,即使测试函数返回false,也会调用iif的第二个参数。这会引发错误,应用程序会立即崩溃。我对RxJS的力量还不熟悉,所以我可能不知道什么。如果有必要的话,我正在使用连接的路由器包

export const roomRouteEpic: Epic = (action$, state$) => action$.ofType(LOCATION_CHANGE).pipe( pluck('payload'), mergeMap(payload => iif( () => { console.log('NOT LOGGED'); return /^\/room\/\d+$/.test(payload.location.pathname); // set as '/login' }, merge( tap(v => console.log('NOT LOGGED TOO')), of( // following state value is immediately evaluated state$.value.rooms.list[payload.location.pathname.split('/')[1]] ? actions.rooms.initRoomEnter() : actions.rooms.initRoomCreate(), ), of(actions.global.setIsLoading(true)), ), empty(), ), ), ); 导出常量RoomRoutePic:Epic=(操作$,状态$)=> 类型(位置更改)的操作$。管道( 弹拨(“有效载荷”), 合并映射(有效负载=> iif( () => { console.log(“未记录”); return/^\/room\/\d+$/.test(payload.location.pathname);//设置为“/login” }, 合并( 轻触(v=>console.log('notlogged TOO'), 的( //立即计算以下状态值 state$.value.rooms.list[payload.location.pathname.split('/')[1]] ?actions.rooms.initRoomEnter() :actions.rooms.initRoomCreate(), ), of(actions.global.setIsLoading(true)), ), 空(), ), ),
); 如果在可观察的创建中使用tap操作符(因为它返回void),将导致如下错误

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()中


我创造了一个新的世界

好的,我自己找到了答案。我的解决方案是完全删除iif,只依赖于mergeMap中的三元运算符。这样,它就不会在每次“位置更改”后以及regExp返回true时进行计算。谢谢你的关注

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,
    ),
  );
export const-roomroutepic:Epic=(action$,state$)=>
类型(位置更改)的操作$。管道(
弹拨(“有效载荷”),
合并映射(有效负载=>
/^\/房间\/\d+$/.test(payload.location.pathname)
?的(
state$.value.rooms.list[payload.location.pathname.split('/')[2]]
?actions.rooms.initRoomEnter()
:actions.rooms.initRoomCreate(),
actions.global.setIsLoading(true),
)
:空,
),
);

参加聚会有点晚,但我发现
iif
的作用不是执行一条路径而不是执行另一条路径,而是订阅一条可观察路径或另一条路径。这就是说,它将执行获取每个可观察对象所需的任何和所有代码路径

从这个例子中

从'rxjs'导入{iif,of,pipe};
从“rxjs/operators”导入{mergeMap};
const source$=of('Hello');
const obsOne$=(x)=>{console.log(`${x}World`);返回('One');
const obsTwo$=(x)=>{console.log(`${x},再见`);返回('Two');
source$.pipe(
合并映射(v=>
iif(
()=>v===‘你好’,
obsOne$(五),
二美元(五)
))
).subscribe(console.log);
您将获得以下输出

Hello World
Hello, Goodbye
One
这是因为,为了获得
obsOne$
它需要打印
Hello World
。这同样适用于
obsTwo$
(除了路径打印
你好,再见

但是,您会注意到它只打印
1
,而不打印
2
。这是因为
iif
评估为
true
,因此订阅
obsOne$


虽然您的三元函数可以工作,但我发现本文很好地解释了一种更受RxJS驱动的实现所需结果的方法:

如果测试函数返回
false
,则应该调用
iif
的第二个参数。如果测试函数返回
true
,将调用第一个参数。请参阅docs By first argument i count测试函数。第二个和第三个在测试后被调用。好的,谢谢你的澄清。接下来,再次检查测试函数是否实际返回
true
。如果它返回除此之外的任何内容,则
iif
将对其求值为
false
。我会尝试用
()=>true
替换您当前拥有的内容,看看是不是
iif
导致了问题,还是您的测试逻辑。非常好地解释了
iif()
执行。