🗂
RxJs Observable の エラーハンドリング
Observable の エラーハンドリング
Observable のエラーは sub.error で出力し、 subscribe の error でキャッチすることができます。
import { Observable } from 'rxjs';
const obs$ = new Observable((sub) => {
sub.next('1');
sub.error(new Error('something wrong'));
console.log("after error") // this message will appear
sub.complete();
});
obs$.subscribe({
next: console.log,
error: console.error,
});
Observable のコンストラクタに渡す関数内で、sub.error のコールは関数の処理進行を妨げないので、
後続の処理はそのまま実行されますが、error を発行したタイミングで値のストリームはクローズされ、
以降で発行される sub.next の処理で流れる値は、subscribe 側で受信できません。
エラーの抑制
以下のように エラーハンドラーを記述しないような subscribe の書き方で subscribe する場合、
発生したエラーはグローバルに送出され、window の error イベントが反応します。
obs$.subscribe({
next: console.log,
});
obs$.subscribe( console.log );
window.addEventListener('error', (event) => {
console.log('error caught');
});
subscribe をシンプルに書きたい場合には、Observable の中でエラーを発生させないことはもちろん重要ですが、
catchError オペレータでエラーを抑制する手段も有効です。
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
const obs$ = new Observable((sub) => {
sub.next('1');
sub.error(new Error('something wrong'));
sub.next('2');
sub.complete();
});
obs$.pipe(
catchError(()=>of(null)
)).subscribe(console.log);
multicast の Hot な Observable においては、
すべての subscribe が Error をハンドリングしなければ、グローバルなエラーが発行されます。
import { Observable } from 'rxjs';
const obs$ = new Observable((sub) => {
sub.next('1');
sub.error(new Error('something wrong'));
console.log('hoge');
sub.complete();
});
const sub = new Subject();
sub.subscribe(console.error); // global error here
sub.subscribe({
error: console.log,
});
obs$.subscribe(sub);
エラーハンドリングの実装例
API のエラー処理
API の結果などは catchError で以下のように処理しておくと利用側での扱いが楽になります。
const user$ = this.userService.getProfile().pipe(
catchError(e => {e})
)
テンプレート側でのエラーの有無は以下のように ngIf が実装可能です。
<div *ngIf="(user$ | async).e">
</div>
Discussion