Angular v18で提供される toSignal()
ユーティリティ関数には ToSignalOptions
を渡すことができます。
https://angular.jp/api/core/rxjs-interop/toSignal
https://angular.jp/api/core/rxjs-interop/ToSignalOptions
ToSignalOptions
の rejectErrors
指定によって挙動がどう変わるのか、試したことを記事に残します。
コードはこちらです。
https://stackblitz.com/edit/stackblitz-starters-a3lr3a?file=src%2Ffoo.component.ts
toSignal()
なんらかの値が不定期に流れるストリームを例にします。
実際にはクリックやリスト選択などユーザーインタラクションを受け取るケースが想定できます。
service = inject(SomeService);
value = toSignal(this.service.observable$, { rejectErrors: false });
クリックでインタラクションを発生させて signals
の値をテンプレートにレンダリングします。また、エラーハンドリングの擬似的な役割としてコンストラクタに console.log()
を起きます。
@Component({
template: `
<button (click)='onNext()'>next</button>
<button (click)='onError()'>error</button>
<p>{{value()}}</p>
`,
...
})
export class FooComponent {
private readonly service = inject(SomeService);
value = toSignal(this.service.observable$, { rejectErrors: false });
constructor() {
effect(() => {
console.log(this.value());
});
}
onNext(): void {
this.service.next();
}
onError(): void {
this.service.error();
}
}
サービスは next()
をコールするたびにカウントを流すシンプルなものです。
@Injectable({ providedIn: 'root' })
export class SomeService {
private count = 0;
private readonly subject$ = new Subject();
get observable$() {
return this.subject$.asObservable();
}
next(): void {
this.count++;
this.subject$.next(this.count);
}
error(): void {
this.subject$.error(new Error('error'));
}
}
rejectErrors:false
toSignal(this.service.observable$, { rejectErrors: false });
この指定はデフォルトです。
ToSignalOptions
を省略しても同じ挙動になります。
まず[1,2,3]を流します。
今度は[1,2,Error]を流します。
Errorの後、インタラクションが発生するたびに signals
の読み取りで console.log()
が実行されます。
エラーハンドリングの処理でモーダル表示などがあると、インタラクションが発生するたびに連続で表示され、意図しない挙動になるかもしれません。
rejectErrors:true
toSignal(this.service.observable$, { rejectErrors: true });
[1,2,Error]を流します。
Errorの後にインタラクションが発生しても console.log()
は実行されません。
エラーハンドリングが初回のみ実行され signals
は最後の値を保持します。
rejectErrors
Angularのドキュメントでは以下のように説明されています。
Whether toSignal should throw errors from the Observable error channel back to RxJS, where they'll be processed as uncaught exceptions.
rejectErrors
はストリームのエラーを Observable
のエラーチャンネルに送出するデフォルトの挙動をリジェクトするか、という指定のようですね。
エラーをリジェクトというのが二重否定のようでイメージしづらかったのですが「エラーの伝搬を止める:TRUE or FALSE」と読み替えて理解できました。