【Angular】あなたのasync pipeは {{ 安全 | async }}ですか?


aysnc pipeとは

PromiseやObservableな非同期オブジェクトをそのままtemplateで表示できるようにしたpipeで
コンポーネントが破棄される時に自動でunsubscribeしてくれる便利なものです。

アンチパターン

oya.page.html
<div>
 親の中で子コンポーネントを呼ぶ
  <app-kodomo [name]="name$ | async">
   私が子コンポーネントです。
  </app-kodomo>
</div>

親コンポーネントでObservableな値を子コンポーネントに渡す

oya.page.ts

name$ = new BehaviorSubject('Hello');

子コンポーネント側でnullを考慮せずに処理している

kodomo.component.ts

@Input() name:string;

ngOnInit(){
 this.name.slice(0, 1);
}

この場合、実行時エラーがでることがあります。

例として、子コンポーネントに渡すときの話をしましたが
以下のように親側でnullを考慮せずに表示しようとする場合も実行時エラーが発生することがあります。

oya.html
   <div>
      {{ name$.slice(0, 1) | async}}
   </div>

原因

AsyncPipeは購読したObservableが最初の値を流す前に、必ず一度 null を返すようにできているからです。

もとのObservableが Observable だったとしても、 AsyncPipeを通すと State | null となってしまいます。

対処方

  • *ngIf や *ngForでnullをガードする
oya.html
   <div *ngIf="name$ | async as name">
      {{ name.slice(0, 1) | async}}
   </div>

  • 子コンポーネント側でnullを考慮した実装をする(これするくらいならAsyncPipe使わない方がいいです。)

参考資料

lacolacoさん
https://blog.lacolaco.net/2020/02/async-pipe-initial-null-problem/

Angular質問箱
https://youtu.be/LVa68EI9NSw?t=990