【Angular】asyncパイプを使おう!【サンプルあり!】

ANGULAR

みなさんこんにちは、現役エンジニアのサメハックです

未経験からWebエンジニアに転職し、
正社員として5年働いたのちフリーランスとして独立しました。

Angularの解説シリーズです。

今回はasyncパイプについて学んでいきましょう!

駆け出しエンジニアや未経験の方、
また新入社員を指導する先輩社員にとっても
わかりやすいように解説していきます!

この記事を読むと・・・
  • asyncパイプの仕組みがわかる
  • asyncパイプと通常の記述の違いがわかる

※PCにnpm、nodeがインストールされている前提で記述します。
 yarn等をお使いの方は読み替えてください。

環境がない人はcodesansboxを使ってね!

実行環境

Angularのバージョンが古いと動かないことがあるよ!
うまく動かなければアップデートしてね!

asyncパイプを使おう

asyncパイプとは

asyncパイプとはObservableまたはPromiseをsubscribe(購読)し、
最新の値を返すAngularのシステムです。

通常subscribe(購読)とunsbscribe(購読解除)はセットで設定する必要がありますが
asyncパイプを使うと、コンポーネントが破棄されたタイミングで
自動的に購読が解除されるのでコードが非常にスッキリするのが特徴です。

TypeScriptで購読せずに直接HTMLに記述出来るよ!

asyncパイプの構文

{{ オブザーバブル | async}}

asyncパイプの問題点 初期値がnullになる

asyncパイプはObservable/Promiseを購読しますが
これらが値を取得する前に画面は描画されてしまうので初期値は必ずnullになり

Cannot read properties of undefined

というエラーが表示されてしまいます。

これらを防ぐためには*ngIfを併用しましょう。

【Angular】条件分岐をしよう!【*ngIf】
*ngIfについてはこちらの記事を参考にしてね!

asyncパイプの構文※実際の使われ方

<ng-container *ngIf="オブザーバブル | async as 別名">
    {{ 別名.プロパティ }}
</ng-container>

このように記述することでオブザーバブルに値が入るまでは
ng-containerが描画されないので、
以下のエラーは出なくなります。

Cannot read properties of undefined
基本的には*ngIfを併用しよう!
ちなみに*ngForでもいいよ!

実際に動かしてみよう!

今回はこのような、Behaviorで保管した値を表示するコンポーネントを
asyncパイプあり/subscribeのみで作成しました。

asyncパイプを使うことでコードがどのように書き換えられるかと、
どれくらいコードがスッキリするかがわかるよ!

コンポーネントの作成

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にあげているので
使いたい人は是非ダウンロードしてみてください。

GitHub - same-hack/Angular-async-pipe: |asyncの使い方解説
|asyncの使い方解説. Contribute to same-hack/Angular-async-pipe development by creating an account on GitHub.

まとめ

  • asyncパイプとはObservableを購読し最新の値を返すシステム
  • 初期値はnullになるので、*ngIfを併用する
  • <ng-container *ngIf=”オブザーバブル | async as 別名”>

満足いただけたら、1クリックなのでSNSフォローしてもらえると嬉しいです🦈

タイトルとURLをコピーしました