1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Angular v18 toSignal()のrejectErrorsオプションの挙動

Posted at

Angular v18で提供される toSignal() ユーティリティ関数には ToSignalOptions を渡すことができます。

https://angular.jp/api/core/rxjs-interop/toSignal
https://angular.jp/api/core/rxjs-interop/ToSignalOptions

ToSignalOptionsrejectErrors 指定によって挙動がどう変わるのか、試したことを記事に残します。

コードはこちらです。
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.gif

今度は[1,2,Error]を流します。

2.gif

Errorの後、インタラクションが発生するたびに signals の読み取りで console.log() が実行されます。

エラーハンドリングの処理でモーダル表示などがあると、インタラクションが発生するたびに連続で表示され、意図しない挙動になるかもしれません。

rejectErrors:true

toSignal(this.service.observable$, { rejectErrors: true });

[1,2,Error]を流します。

3.gif

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」と読み替えて理解できました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?