みなさんこんにちは、現役エンジニアのサメハックです
未経験からWebエンジニアに転職し、
正社員として5年働いたのちフリーランスとして独立しました。
Angularの解説シリーズです。
今回はasyncパイプについて学んでいきましょう!
駆け出しエンジニアや未経験の方、
また新入社員を指導する先輩社員にとっても
わかりやすいように解説していきます!
- asyncパイプの仕組みがわかる
- asyncパイプと通常の記述の違いがわかる
※PCにnpm、nodeがインストールされている前提で記述します。
yarn等をお使いの方は読み替えてください。
実行環境
うまく動かなければアップデートしてね!
asyncパイプを使おう
asyncパイプとは
asyncパイプとはObservableまたはPromiseをsubscribe(購読)し、
最新の値を返すAngularのシステムです。
通常subscribe(購読)とunsbscribe(購読解除)はセットで設定する必要がありますが
asyncパイプを使うと、コンポーネントが破棄されたタイミングで
自動的に購読が解除されるのでコードが非常にスッキリするのが特徴です。
asyncパイプの構文
{{ オブザーバブル | async}}
asyncパイプの問題点 初期値がnullになる
asyncパイプはObservable/Promiseを購読しますが
これらが値を取得する前に画面は描画されてしまうので初期値は必ずnullになり、
Cannot read properties of undefined
というエラーが表示されてしまいます。
これらを防ぐためには*ngIfを併用しましょう。
asyncパイプの構文※実際の使われ方
<ng-container *ngIf="オブザーバブル | async as 別名">
{{ 別名.プロパティ }}
</ng-container>
このように記述することでオブザーバブルに値が入るまでは
ng-containerが描画されないので、
以下のエラーは出なくなります。
Cannot read properties of undefined
ちなみに*ngForでもいいよ!
実際に動かしてみよう!
今回はこのような、Behaviorで保管した値を表示するコンポーネントを
asyncパイプあり/subscribeのみで作成しました。
どれくらいコードがスッキリするかがわかるよ!
コンポーネントの作成
ng new my-angular
ng generate component async-pipe
ng generate component subscribe
ng serve -o
app.component.html
<app-async-pipe></app-async-pipe>
<app-subscribe></app-subscribe>
subscribeを使ったコンポーネント
subscribe.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable, Subscription, BehaviorSubject } from 'rxjs';
// User型
export interface User {
name: String;
age: number;
job: String;
}
@Component({
selector: 'app-subscribe ',
templateUrl: './subscribe.component.html',
styleUrls: ['./subscribe.component.scss'],
})
export class SubscribeComponent implements OnInit {
// 初期値用
data = {
name: 'サメハック',
age: 29,
job: 'エンジニア',
};
// ユーザの持つ値を保管する
user$ = new BehaviorSubject(this.data);
// | async を使わない場合の記述
myUser: User;
ngOnInit(): void {
// subscribeして値を購読する必要あり
this.user$.subscribe((res) => {
this.myUser = res;
});
}
ngOnDestroy(): void {
// 購読を解除
this.user$.unsubscribe();
}
}
subscribe.component.html
<h2>| asyncを使わない</h2>
<p>{{ myUser.name }}</p>
<p>{{ myUser.age }}</p>
<p>{{ myUser.job }}</p>
asyncを使ったコンポーネント
async-pipe.component.ts
import { Component } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
// User型
export interface User {
name: String;
age: number;
job: String;
}
@Component({
selector: 'app-async-pipe',
templateUrl: './async-pipe.component.html',
styleUrls: ['./async-pipe.component.scss'],
})
export class AsyncPipeComponent {
// 初期値用
data = {
name: 'サメハック',
age: 29,
job: 'エンジニア',
};
// ユーザの持つ値を保管する
// | asyncを使ったので購読(subscribe),購読解除(unsubscribe)が不要
user$ = new BehaviorSubject(this.data);
}
async-pipe.component.html
<h2>| async</h2>
<!-- ↓ これはエラーになる -->
<!-- {{ user$.name }} -->
<!-- | asyncを使ったので、TypeScript側でsubscribe,unsubscribeが不要 -->
<!-- ※ | asyncを使うと初期値がnullになるので、*ngIfを併用する -->
<ng-container *ngIf="user$ | async as user">
<!-- user$が値を受け取ってからDOMを描画 -->
<p>{{ user.name }}</p>
<p>{{ user.age }}</p>
<p>{{ user.job }}</p>
</ng-container>
これでnpm startすると同じものが完成します。
GitHubのサンプルコード
今回作ったものはGitHubにあげているので
使いたい人は是非ダウンロードしてみてください。
まとめ
- asyncパイプとはObservableを購読し最新の値を返すシステム
- 初期値はnullになるので、*ngIfを併用する
- <ng-container *ngIf=”オブザーバブル | async as 別名”>
満足いただけたら、1クリックなのでSNSフォローしてもらえると嬉しいです🦈