【问题标题】:@ngrx effects prevent switchmap break on error@ngrx 效果防止 switchmap 因错误而中断
【发布时间】:2018-01-26 14:07:29
【问题描述】:

在注册过程中我有 3 个 http 调用:向身份验证提供商注册,在 api 中创建帐户,然后登录。

如果使用身份验证提供商注册失败(例如帐户已存在),它仍会尝试在 api 中创建帐户。 如果我在 @Effect 末尾添加一个 catch,第二次尝试(比如更正的凭据)将不再调用该效果。

如何防止后续的(accountSercice.CreateAccount 和 authenticationService.Login)switchMaps 运行?

@Effect() AccountSigningUp$ = this.actions$
.ofType(ACCOUNT_SIGNING_UP)
.map((action: AccountActions.AccountSigningUp) => action.payload)
.switchMap(signUpModel => this.authenticationService.SignUp(signUpModel)
    .catch(err => {
        let signUpModel = new SignUpModel();
        signUpModel.message = err;
        return Observable.of(new AccountSignUpFailed(signUpModel))
    })
    .switchMap(signUpModel => this.accountService.CreateAccount((signUpModel as SignUpModel))
        .catch(err => {
            let signUpModel = new SignUpModel();
            signUpModel.message = err;
            return Observable.of(new AccountSignUpFailed(signUpModel))
        })
    )
    .switchMap(loginModel => this.authenticationService.Login((loginModel as LoginModel))
        .map(tokenModel => {
            this.tokenService.Save(tokenModel);
            return new AccountLoggedIn();
        })
        .catch(err => {
            let loginModel = new LoginModel();
            loginModel.message = err;
            return Observable.of(new AccountLoginFailed(loginModel))
        })
    )
    .map(() => new AccountCreated())
);

【问题讨论】:

  • 仅供参考,从 catch 运算符返回 Observable.of(...) 就像标准的 try/catch 一样,代码将在 catch 之后继续(在本例中为流)。从 catch 运算符返回 Observable.throw(...) 就像在 try/catch 中重新抛出一个错误,它会冒泡直到被捕获(在这种情况下,跳过流中的所有其他运算符,直到它遇到捕获或错误回调订阅)。我只是分享一下,以供您理解。正确的答案已经提出(设置单独的效果来触发彼此的成功)。

标签: angular typescript rxjs ngrx ngrx-effects


【解决方案1】:

您可以为此场景创建三种不同的效果。并在第一次完成时调用另一个效果。像这样的 -

/**
* Effect For Auth service
*/
@Effect() authenticationService$ = this.actions$
.ofType(AUTH_SERVICE)
.map((action: AccountActions.AccountSigningUp) => action.payload)
.switchMap(signUpModel => this.authenticationService.SignUp(signUpModel)
.map(res =>({ type: action.CREATE_ACCOUNT, payload: res.json()}))
.catch(() => Observable.of({ type: action.AUTH_SERVICE_FAILED }))
)




/**
    * Effect For Create Account service
    */
    @Effect() authenticationService$ = this.actions$
    .ofType(CREATE_ACCOUNT)
    .map((action: AccountActions.AccountSigningUp) => action.payload)
    .switchMap(signUpModel => this.accountService.CreateAccount((signUpModel as SignUpModel))
    .map(res =>({ type: action.LOGIN, payload: res.json()}))
    .catch(() => Observable.of({ type: action.CREATE_ACCOUNT_FAILED }))
    )

    /**
    * Effect For Login service
    */
    @Effect() authenticationService$ = this.actions$
    .ofType(LOGIN)
    .map((action: AccountActions.AccountSigningUp) => action.payload)
    .switchMap(signUpModel => this.authenticationService.Login((loginModel as LoginModel))
    .map(res =>({ type: action.LOGIN_SUCCESS, payload: res.json()}))
    .catch(() => Observable.of({ type: action.LOGIN_FAILED }))
    )

如果你想在成功调用中调用两个操作,你可以像这样使用 mergeMap。

@Effect() authenticationService$ = this.actions$
.ofType(LOGIN)
.map((action: AccountActions.AccountSigningUp) => action.payload)
.switchMap(signUpModel => this.authenticationService.Login((loginModel 
 as LoginModel))
.mergeMap((response) =>            
 return[
     ({ type: action.FIRST_ACTION, payload: response.json() }),
     ({ type: action.SECOND_ACTION, payload: response.json()})
      ];
 });

【讨论】:

  • 感谢您的旅游建议。我确实对登录有影响,但是由于某种原因它没有被调用,因此为什么我有登录代码。我可以再试一次
  • 谢谢,我照做了,现在可以了。但是,它还不是 100%,因为 CREATE_ACCOUNT 需要触发两个操作:LOGIN 和 ACCOUNT_CREATED。任何想法如何实现这一目标?
  • 您可以在服务调用后使用mergeMap。它基本上返回一个动作数组。
  • @WPalombini 我已经更新了代码,希望对您有所帮助。
  • 感谢您的及时回复。我确实尝试过,但似乎它不尊重订单。注册页面订阅了 ACCOUNT_CREATED 操作,然后重定向用户。它正在尝试重定向用户,但登录尚未完成,这会导致与未通过身份验证相关的错误。有没有办法让动作按顺序运行?
猜你喜欢
  • 2019-06-27
  • 1970-01-01
  • 2018-12-09
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 2018-10-01
  • 2019-03-10
相关资源
最近更新 更多