🎈

はじめましてAngular

2022/12/19に公開

はじめに

この記事は、Angular Advent Calendar 2022 19日目の記事です。
https://qiita.com/advent-calendar/2022/angular
Angular Advent Calendar もそろそろ後半戦ですね。盛り上げていきましょう〜

今回は、「はじめましてAngular」ということで、Vue.jsやReactといった他のフロントエンドフレームワークを3年以上触ってきたフロントエンドエンジニアの私がはじめてAngularと出会い、少しづつ歩み寄っていく物語です。

Angular以外のフロントエンドフレームワークを触っていたりしていて、はじめてAngularに触れる方や、Angularにとっつきづらいなあと思ってる方に、どういうことを考えながらはじめての学習をしているかが届いたら幸いです。

Angularとの出会いと戸惑い

はじめて、Angularと出会ったのは、転職を通じてでした。
転職のモチベーションにフレームワークについてそこまでこだわっていなかったので、今の職場に縁がありAngularを知ることとなりました。

もとから、Angularは、3大フロントエンドフレームワークとして、React, Vueに並んでいながらもそこまでの人気はなく、私自身も、Angualrのことは他の関数型プログラミングの流行に逆行した、OOP(Object Oriented Programming)ライクなのはどうしてかなあと思いつつ、実際転職するまでAngularのことはほとんど目にはありませんでした。

とりあえず、Angularチュートリアルをざっくりみてみます。
このチュートリアルはちゃんとできていて、angular-tour-of-heroes を作りつつ、他フレームワークでもできるような、状態の伝搬方法、コンポーネントのライフサイクルイベントやルーティングなどなど、基本的な作りを一通り確認できそうでした。

しかして、Angularに出会った私ですが、非同期処理のコードを見た瞬間、Angularとは仲良くなれなさそう...と思ってしまいます。

当時の私
「なにこれ..仲良くなれなさそう...。」

user.component.html
<div *ngIf="user | async as user">
    <p>{{ user.name }}</p>
</div>
user.component.ts
@Component({
  selector: 'app-user',
  template: './user.component.html'
})
export class UserComponent {
  public user$: Observable<User>;

  constructor(private route: ActivatedRoute, private userService: UserService) {
    // Routerから取得したIDからユーザデータを取得するような処理
    this.user$ = this.route.paramMap.pipe(
      // id を 取得
      map(params => params.get('id')),
      // Observable<User> にストリームを変更
      switchMap(id => this.userService.fetch(id)) 
    )
  }
}

今まで、職場ではVue.js、個人開発ではReactを利用していました。そのため、ずっとasync/awaitPromiseな非同期処理を書いていた私としては、Observableを利用した、非同期処理をみて、戸惑いを隠しきれませんでした。

調べるうちに、AngularはRxJSライクなフレームワークで、基本的にPromiseではなく、 Observableを利用する(Promiseをあえて利用する場合もある)ということみたいです。

RxJSってそもそもどういうものなのでしょうか?
一度、公式ドキュメントを開くことにします。

RxJSってなに...?

Angularを他のReactやVue.jsなどのフレームワークと見比べる時に、大きな違いになってくるのは、RxJSライクというところと、OOP(Object Oriented Programming)ライクというところではないでしょうか?
AngularがOOPライクという点については、サーバサイドプログラミングに慣れている人には、馴染み深いなど、メリデメがわかりやすいので、ここでは触れないでおこうと思います。

RxJSとは

RxJS is a library for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code.

RxJSとは、Observableを利用した、リアクティブプログラミングのためのライブラリで、コールバックベースのコードや、非同期なコードをより使いやすくします。

ということなので、ちゃんと理解するためには、Observableについて深掘りする必要があるみたいですね。

ReactiveX combines the Observer pattern with the Iterator pattern and functional programming with collections to fill the need for an ideal way of managing sequences of events.

また、ReactiveX(固有名詞)は、理想的なイベント管理のためにObserverパターンをIteratorパターンと関数型プログラミングとをコレクションに紐づけます。

ということなので、詳細な理解のためには、ObserverパターンIteratorパターンデザインパターンの1つ)の理解も必要ということみたいです。

でもこれだけでは、Observableってどのように使うのかまだわかりませんね...。

Observableについて

Observables are lazy Push collections of multiple values.

Observavleは、実行遅延コレクション?(訳すの自信ない...)みたいです。
そもそも、それはなに...?みたいになると思いますが、一旦実コードで理解していきましょう。
例に、非同期処理でよく例に出される、sleep関数を実装するとします。

以下、Promiseの場合と、Observableの場合で比較していきましょう。

sleep.ts
import { of } from 'rxjs'; // of()で、Observableな値を作成できます。
import { delay, tap } from 'rxjs/operators';

// Promiseの場合
const sleepPromise = (msec) => new Promise((resolve) => setTimeout(resolve, msec))

// Observableの場合
// setTimeout()と似た機能がdelay()で提供されているみたい
const createSleepObserver = (msec: number, cb: () => void) => of(0)
    .pipe(delay(msec), tap(() => cb())) 

次に、作成した関数を利用してみましょう。

sleep.ts
// Promiseの場合
const sleepA = async () => {
    await sleepPromise(1000);
    console.log('sleep 1000');
}
sleepA();

// Observableの場合
const sleepB = () => {
    // subscribe()で購読されるまで、実行されません。
    // Obsevableな変数には、prefixで末尾に$をつけるといいみたい。
    const sleep$ = createSleepObserver(1000, () => {
        // sleepしたい処理を書く
        console.log('sleep 1000')
    });
    // 購読を開始する。
    sleep$.subscribe();
}
sleepB();

 sleepA()はawaitを利用するため、不必要に関数にasyncをつけないといけませんが、sleepB()の非同期処理はシンプルです。わかりやすいように関数に切り出しましたが、createSleepObserver()から返却されたObservableな値が格納されたsleep$のスコープに閉じていますね。
pipe()やコールバック関数で処理を記述しているのを見るに、Node.js(CommonJS)の非同期なイベントドリブンな書き方にとても似ています。また、購読されるまで実行が遅延されるというところをみるに、実行遅延コレクション?というのもそういうことなのでしょうか。

さて、なにげなく「subscribe()」や「購読」の文字を出してしまいましたが、素通りしちゃうところでした、これはなに..?
調べてみると、RxJSのObsevableの概念を理解するには、「購読」という概念も同時に理解しないとダメみたいです。
RxJSの購読やObservableのその他詳しい内容については、アドカレ作成者の @lacolaco さんの以下の本を参考にした方が理解が進むと思いますので、気になった方はご一読ください。
https://zenn.dev/lacolaco/books/angular-after-tutorial/viewer/observable-concept

実際他のフレームワークと比べてAngularってどうなの?

3大フレームワーク全部に触れて、3大フロントエンドフレームワークと呼ばれるReact, Vue, Angularに限っていうと、どのフレームワークも利用する層が違うということが言えると思います。細かいことをいうと、ポジショントークになってしまうので言及しませんが、流行ってるのには相応の理由があると思います。

また、Angularは落ち目だと言われていますが、エンジニアとってとても魅力のあるフレームワークだとも思います。RxJSの理解をすることは、他のフレームワークでは味わえない新たな技術パラダイムに触れる楽しさがあるかなあと思いますし、その世界はプログラミング言語自体への理解をより深めてくれると思います。

おわりに

今回は、「Angularはじめまして」というタイトルで、はじめてAngularを触ってどのように学んでいったか、他のフレームワークと比べてどう感じたかを書かせていただきました。今後は、RxJSにもう少し踏み込んでみたいなあと思ってます。(その記事も書けるといいなあ。マサカリはこわいですが)

まだまだ、Angularのことはちゃんと理解できてなかったりするので、なにかコメントなどありましたら気軽にお願いします!!
最後に、Angular Advent Calendar 2022もまだまだ続きますので、一緒に盛り上げていきましょう。

Discussion