【问题标题】:@ngrx Effect does not run the second time@ngrx Effect 没有第二次运行
【发布时间】:2017-10-26 02:17:29
【问题描述】:

我刚刚开始了解@ngrx/store 和@ngrx.effects,并在我的Angular/Ionic 应用程序中创建了我的第一个效果。它第一次运行正常,但如果我再次将事件发送到商店(即再次单击按钮时),什么也没有发生(没有进行网络调用,控制台日志中没有任何内容)。有什么明显的我做错了吗?效果如下:

@Effect() event_response$ = this.action$
    .ofType(SEND_EVENT_RESPONSE_ACTION)
    .map(toPayload)
    .switchMap((payload) => this.myService.eventResponse(payload.eventId,payload.response))
    .map(data => new SentEventResponseAction(data))
    .catch((error) => Observable.of(new ErrorOccurredAction(error)));

谢谢

【问题讨论】:

    标签: effects ngrx


    【解决方案1】:

    听起来好像发生了错误。在这种情况下,catch 返回的 observable 中的动作将被发送到效果的流中,然后效果将完成 - 这将阻止效果在错误动作发出后运行。

    mapcatch 移动到switchMap

    @Effect() event_response$ = this.action$
      .ofType(SEND_EVENT_RESPONSE_ACTION)
      .map(toPayload)
      .switchMap((payload) => this.myService
        .eventResponse(payload.eventId, payload.response)
        .map(data => new SentEventResponseAction(data))
        .catch((error) => Observable.of(new ErrorOccurredAction(error)))
    );
    

    switchMap 中组合catch 会在发生错误时阻止效果完成。

    【讨论】:

    • 这是否意味着使用 Angular 的全局错误处理程序无法使用效果? stackoverflow.com/questions/47896171/…
    • 对于pipeable 运算符和catchError 仍然如此。我花了一段时间才找到这个问题!谢谢。
    • 供参考 - 您可以在不进入回调地狱的情况下执行此操作,只需在管道末尾添加一个 catchError:github.com/ngrx/platform/issues/646#issuecomment-398640097
    • @亚当尼斯。但是,我建议返回 caught.pipe(startWith(/* error action */)) 而不是通过商店显式调度 - 正如链接的 GitHub 评论中所做的那样 - 我认为这不是我认为应该做的事情。
    • @cartant - 这又回到了管道的内部。你能做到吗:.pipe(...,catchError((err,caught) => caught),startWith(() => /* error action */)?我发现在效果中做 store.dispatch 也很恶心,我只是觉得它比把管道放在管道里更恶心。
    【解决方案2】:

    您必须将map()catchError() 移动到swithchMap(),如下所示

    @Effect()
    public event_response$ = this.action$.pipe(
        ofType(SEND_EVENT_RESPONSE_ACTION),
        switchMap((payload) => {
            return this.myService.eventResponse(payload.eventId,payload.response).pipe(
                map((data: DataType) => new SentEventResponseAction(data)),
                catchError((error) => Observable.of(new ErrorOccurredAction(error)))
            })
        );
     );
    

    请注意,myService 中的 evetResponse() 方法应该返回一个 observable 以便之后使用管道。 如果你在服务中的方法返回Promise,你可以通过使用rxjs包中的from将它转换成一个observable,如下所示:

    import { from } from 'rxjs';
    ...
    const promise = this.myService.eventResponse(payload.eventId,payload.response);
    const observable = from(promise);
    return observable.pipe(...
    

    更多详细介绍请看link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-15
      • 2018-06-30
      • 2021-07-21
      • 1970-01-01
      • 1970-01-01
      • 2017-06-16
      • 2013-06-15
      • 1970-01-01
      相关资源
      最近更新 更多