@ngrx 效果防止 switchmap 在错误时中断
@ngrx effects prevent switchmap break on error
我在注册过程中有 3 个 http 调用:注册身份验证提供商,在 api 中创建帐户,然后登录。
如果与身份验证提供商的注册失败(比如帐户已经存在),它仍会尝试在 api 中创建帐户。
如果我在 @Effect 的末尾添加一个 catch,第二次尝试(比如更正的凭据)将不再调用该效果。
如何防止来自 运行 的后续(accountSercice.CreateAccount 和 authenticationService.Login)switchMap?
@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())
);
您可以为这个场景创建三种不同的效果。并在第一次完成时调用另一个效果。像这样 -
/**
* 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()})
];
});
我在注册过程中有 3 个 http 调用:注册身份验证提供商,在 api 中创建帐户,然后登录。
如果与身份验证提供商的注册失败(比如帐户已经存在),它仍会尝试在 api 中创建帐户。 如果我在 @Effect 的末尾添加一个 catch,第二次尝试(比如更正的凭据)将不再调用该效果。
如何防止来自 运行 的后续(accountSercice.CreateAccount 和 authenticationService.Login)switchMap?
@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())
);
您可以为这个场景创建三种不同的效果。并在第一次完成时调用另一个效果。像这样 -
/**
* 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()})
];
});