ngrxエフェクトのswitchMapでErrorをスローする方法
Aug 19 2020
私はngrx8、rxjs6、angular9を使用しています
ログイン後、別のサービスに電話する必要があります。そのサービスがエラーをスローしているとき、それを処理するためにエフェクトのcatchError部分が必要です。問題は、try catchでエラーをキャッチし、ログを表示しますが、catchError
トリガーされないことです。
簡略化されたコード
login$ = createEffect(() => { return this.actions$.pipe(
ofType(AuthActions.login),
switchMap((action) =>
this.userService.login(action.userName, action.password)
.pipe(
switchMap((token) => {
return throwError(new Error('hello'));
}),
map((token) => AuthActions.loginSuccess()),
catchError((error) => {
console.error('error', error); // I don't see this in console
return of(AppError({ error }));
})),
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
}),
);
});
私の本当のコード
login$ = createEffect(() => { return this.actions$.pipe(
ofType(AuthActions.login),
switchMap((action) =>
this.userService.login(action.userName, action.password)
.pipe(
switchMap(async (token) => {
try {
await this.matrixService.initClient(action.userName, action.password);
return of(token);
}
catch (error) {
console.log('catch error', error); // I see this in console
return throwError(error);
}
}),
map((token) => AuthActions.loginSuccess()),
catchError((error) => {
console.error('error', error); // I don't see this in console
return of(AppError({ error }));
})),
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
}),
);
});
コンソール出力

回答
1 RafiHenig Aug 19 2020 at 04:23
Async-Await
構文を使用してPromise
戻り値matrixService.initClient
が完了するのを待つのではなく(switchMap
演算子がasync
関数を待機していないため、現在のコンテキストでは機能しません)、Observable
(switchMap
演算子のおかげで)に変換されるため、待機せずに返すことを検討してください。)を受け入れるPromise
とthis.userService.login
、待たされます。
login$ = createEffect(() => this.actions$
.pipe(
ofType(AuthActions.login),
switchMap(({ userName, password }) => this.userService.login(userName, password)
.pipe(
switchMap(() => this.matrixService.initClient(userName, password)),
map((token) => AuthActions.loginSuccess()),
catchError((error) => {
console.error('error', error);
return of(AppError({ error }));
})
)
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
})
)
);
HamzaZaidi Aug 19 2020 at 22:01
コメントに基づいて、前の回答を少し変更します
login$ = createEffect(() => this.actions$
.pipe(
ofType(AuthActions.login),
switchMap(({ userName, password }) => this.userService.login(userName, password)
.pipe(
map((token) => AuthActions.loginSuccess())
tap(() => this.matrixService.initClient(userName, password)),
)
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
})
)
);
私は順序を切り替え、常に発砲AuthActions.loginSuccess()
してからthis.matrixService.initClient(userName, password)
。
catchError
2回呼び出す必要はありません。サービス呼び出しから生成されたエラーは、最も外側のcatchError
オペレーターでキャッチされます。