【问题标题】:Ngrx Effects Calling API and Comparing with StoreNgrx Effects 调用 API 与 Store 对比
【发布时间】:2019-10-10 04:29:50
【问题描述】:

所以我已经尝试了 2 天来解决这个问题,但我放弃了,rxjs 非常棘手,特别是对于 map 家庭。

我有一个以id为参数的动作MessageRequested,它应该启动一个api调用来获取消息,然后检查相应的访问者是否在商店中。如果它不在商店中,它将发送两个动作,MessageLoaded 和 VisitorRequested。如果它在商店中,我们将只发送一个操作,MessageLoaded。所以逻辑应该是这样的:

  1. MessageRequested 以 id 作为输入进行调度
  2. 现在我们调用以id为参数的api,我们返回了一个Message对象。消息定义如下。它有一个visitor_id 属性:mergeMap((action) => this.converseService.getMessage( action[0].message_id ))
  3. 现在我们查询商店,Message对象中的visitor_id是否存在于Visitor状态(this.store.pipe(select(selectVisitorById( m.visitor_id ) ))
  4. 现在我们有了一个需要应用的 if 条件,

    一个。如果select 返回了一些东西,那么访客已经在商店中,我们将只返回MessageLoaded 操作。

    b.如果select 没有返回visitor,我们现在必须发送一个额外的操作VisitorRequested 来请求访问者。我们仍然需要发送MessageLoaded 操作。这就是 2 个动作。

现在是代码:

    loadMessage$ = this.actions$
        .pipe(
            ofType<MessageRequested>(MessageActionTypes.MessageRequested),
            mergeMap((action) => this.converseService.getMessage( action[0].message_id )),
            map(m => m.model),
            withLatestFrom(  this.store.pipe(select(selectVisitorById( m.visitor_id ) ))),
            tap( ([message,visitor]) => {
                if (visitor == null) new VisitorRequested(message.visitor_id);
            }),
            map( ([message, visitor]) => {
                return new MessageLoaded({message});
            } )
        );
export class Message {
    id: number;
    message: string;
    visitor_id: number;
    is_from_visitor: boolean;
    created_at: string;
}

export class MessageResponse extends Response {
  model: Message
}

export class Response{
  message:String;
  didError: boolean;
  errorMessage: string;
}

代码看起来没问题,只是withLatestFrom 不接受输入,所以我无法传递m.visitor_id 变量,现在我不得不想另一种方法。我尝试使用forkJoin 和concatMap,但没有成功。

在场景中使用哪些合适的运算符?

更新 #1

在所有答案的帮助下,这终于奏效了:

    @Effect()
    loadMessage$ = this.actions$
        .pipe(
            ofType<MessageRequested>(MessageActionTypes.MessageRequested),
            mergeMap((action) => this.converseService.getMessage( action.message_id )),
            map(m => m.model),
            concatMap(message =>
                of(message).pipe(
                  withLatestFrom(this.store.pipe(select(selectVisitorById(message.visitor_id))))
                )
            ),            
            tap( ([message,visitor]) => {
                if (!(visitor)) this.store.dispatch(new VisitorRequested(message.visitor_id));
            }),
            map( ([message, visitor]) => {
                return new MessageLoaded({message});
            } )
        );

【问题讨论】:

    标签: angular rxjs ngrx ngrx-effects


    【解决方案1】:

    tap 不返回值,它只是一个 void。 相反,根据条件返回一个动作数组:

     switchMap(([message,visitor]) => {
        if (visitor == null) return [new VisitorRequested(message.visitor_id), new MessageLoaded({message})];
        return [new MessageLoaded({message})]
     })
    

    恕我直言,更正确的答案是有两种效果:

    1) 收听MessageActionTypes.MessageRequested 并发送MessageLoaded 2) 收听MessageActionTypes.MessageRequested 并发送VisitorRequested 如果它不在商店里。甚至,把VisitorRequested的逻辑放到这个效果里。

    【讨论】:

    • 但是如何将 m.visitor_id 传递给 withLatestFrom,因为它不接受任何输入
    • 你在文章中指出了正确的答案,我用最终有效的方法更新问题
    【解决方案2】:

    如果您想将 store 中的一些数据与 action 中的数据一起传递,您可以将 map 函数传递给 withLatestFrom():

    someEffect$ = createEffect(() =>
            this.actions$.pipe(
                ofType(SOME_ACTION),
                withLatestFrom(this.store.select(yourFeature), (action, data) => ({ dataFromStore: data, payload: action.payload })),
                switchMap(props => {
                    // do something fun
                })  
            )
        );
    

    如https://ngrx.io/guide/effects 中所述,还建议将 withLatestFrom 包装在一个展平运算符中,因为 withLatestFrom 将立即通过select() 侦听,无论有什么动作进入。

    concatMap(action => of(action).pipe(
         withLatestFrom(this.store.pipe(select(yourFeature)))
    ))
    

    【讨论】:

    • 但是如何结合来自动作的数据,以及来自商店的数据,以及来自 API 的数据,如示例中所示
    猜你喜欢
    • 2018-04-18
    • 1970-01-01
    • 2016-12-28
    • 2019-03-02
    • 2017-07-19
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    相关资源
    最近更新 更多