角度で宣言、反応、データ、アクションストリーム



ファースト・シング
前に行って、紹介を取得しましょう.私はチャンドラー、アラバマ州からの完全なスタックのdevは、角とWeb技術に焦点を当てた.現在、私はエンジニアリングチームにいますnSide , 私が現在様々な装置のためにiotダッシュボードを構築している学校安全性プラットホーム.

TLR
アクションとデータストリームを使用して、ユーザーアクションに反応するように宣言できます.RXJS演算子のパワーを活用することで、データを変換し、我々のテンプレートがasyncパイプを使用してオブザーバブルを購読できます.Stackblitzはここにあります.

そのタイトルには、大きな怖い言葉がたくさんある
私はそれを取得する場合は、その角度は、文が圧倒的になる可能性がある場合は、反応の意味は何ですか?何が宣言ですか?OK、私が得るデータ取得と私はHTTPクライアントについて知っているが、あなたは何について話していますか?まず第一にいくつかの重要な用語、いくつかの基本的な基礎を釘にしましょうし、そこから繰り返してみましょう.この記事では、私はまだ旅を始めているあなたを取ることを願っています.始めましょう!

クライアント
私がここで作っているいくつかの基本的な仮定があります.まず最初に、私はあなたが医者のこの点まで角度を知っていると思いますhttps://angular.io/tutorial/toh-pt6 . 第二に、これは私が間違いなく教える資格がないという一連のポストを必要とするRXJSに関する詳細なポストであるつもりではありません、しかし、私はオブザーバーブル、主題と購読のようなものの若干の基本知識を仮定します.
したがって、一般的に角度のアプリケーションでは、サーバーからいくつかのデータを取得し、ユーザーのためにそれを表示し、対話を表示する必要があります.ほとんどの時間のような方法を使用します.
getUsers() {
    return this.http.get<Users[]>(`${this._rootUrl}/users`)
        .pipe(catchError(err=> (
            this.handleError(err)
    ))
}
良い方法に従って、このメソッドは、我々のサービスに住んでいて、コンポーネントが初期化されたときにコンポーネント内で呼び出されます.
ngOnInit(): void {
//dont forget to unsubscribe! 
    this.subcription = this.userService.getUsers()
        .subscribe(res => this.users = res)
}
次に、クラスのユーザープロパティを使用して、テンプレート内の構造ディレクティブを使用してUIを表示できます.

<div *ngFor="let user of users">{{user.name}}</div>

これは完全に有効な方法ですが、より良い方法がありますか?
これは私が質問を始めた質問です.いくつかの改善が可能です.私は、具体的にはAsync Pipe 私は自分の購読を管理する必要はありませんので、観察できるように購読する.それ自体は巨大な勝利であり、これが多くの人々が使用するテクニックになります.しかし、私は満足していませんでした、そして、私は2つの異なるAPIからデータをとることに関与している仕事でこの問題に乗りました.パターンのような手順を使用すると、私に解決策のように感じられなかった.それから、私はデボラKurataから話を見て、より多くを学ぶために空腹でした.宣言と反応のアプローチで入力します.

鍵語
まず最初に、どのような反応的で宣言的な意味について話しましょう.初心者にとっては、コーディングのような命令や手続きを認識するかもしれません.これは、あなたが達成したいものの各ステップを記述する場所です.たとえば、フォルダ構造内で深くネストされているファイルシステム内の特定のファイルに移動したいとします.あなたはそこにあるすべてを覚えていないし、端末を使用することができます.あなたはたくさんやりますls and cd あなたが行く必要がある場所まで.それらは手続きです.あなたが行く場所になるまで正確に各ステップを記述している.さて、宣言的なアプローチはどうでしょう?単に言うwhatever-the-file-is それから、機械は残りの部分を自分で見つけ出す.マシンがどのようにそれをするかを知っているならば、これは素晴らしいです、しかし、大部分の時間はそうしません、そして、我々は我々が何をしたいか、そして、それを成し遂げるすべてのステップを記述する必要があります.今リアクティブなプログラミングを説明するのは少し難しいと私はこの記事にパントしようと思うhttps://gist.github.com/staltz/868e7e9bc2a7b8c1f754
しかし、それの不足はそうです...
//C REACTS to changes in a or b
let a = 1;
let b = 2;
let c = a + b; //3 at this point in time
b = 3;
// C will now be 4. It recomputed its value based on changes to the things that make up its value.

宣言的データストリーム
今、我々はどこで我々がどこに行こうとしているかについて話しましょう知っています.データストリームを宣言しましょう.
allUsers$ = this.http.get<User[]>(`${this._baseUrl}/users`).pipe(
    map(users =>
      users.map(
        user =>
          ({
            ...user,
            username: `${user.username}@${user.website}`
          } as User)
      )
    ),
    catchError(err => {
      console.error(err);
      return throwError(err);
    }),
    shareReplay(1)
  );
それで、このコードの故障をしましょう.我々のサービスでは、私たちはクラスと呼ばれるプロパティを宣言していますallUsers$ . 今、最後に$はコミュニティのコンベンションで、これが観測可能なストリームであることをお知らせします.RXJS演算子を活用することで、我々は任意の種類のデータ変換を行うことができますmap 演算子を受け取るUser[]Array.map() あらゆるUser objectという名前の新しいオブジェクトを返します.それから、私たちは、私たちのタイピングが台無しにされて、TSがタイプを推論することができなかった場合、その戻り値を良い処置のためにユーザとしてキャストしました.次に、エラー処理を行いますcatchError . 今、一般的にはLogger サービスとサーバのログをどこかに保存しますが、今のところコンソールでエラーが発生します.私がここでそれをするので、問題があったならば、我々がそれであったサービスでわかることができて、それから我々は帰りますthrowError したがって、それは我々(我々の構成要素)に加入するオブジェクトまで伝播します、そして、彼らはそこでそれを扱うことができます.最後に、我々shareReplay(1) . これは、誰かが後で観測可能に購読するならば、我々がすでに得たデータをキャッシュして、再利用するのを許します.たとえば、異なる時間で観測可能なものを購読する2つのコンポーネントがあるとします.最初の加入者はHTTPリクエストをキックオフします.我々は結果を共有して、再生しているので、次の加入者は最初のものがした価値を得ます、そして、もう一つのHTTP呼び出しは作られません.

データストリームの使用方法
データストリームを使用すると信じられないほど簡単です!ここではストリームを使用するためのレシピです.
  • ターゲットコンポーネントにサービスを注入するprivate userService: UsersService
  • サービスからデータストリームの参照をキャプチャします.例えば.
  • this.users$ = this.userService.allUsers$.pipe(
    //Our error thrown from the service bubbles to the component where we handle
    //it. I'm just simply setting a property to true
    //You have to return an Observable so I just return a empty observable that completes
          catchError(err => {
            this.error = true;
            return EMPTY;
          })
        );
    
  • 今すぐ私たちのテンプレートからの非同期パイプを購読する!
  • <ng-container *ngIf="users$ | async as users">
    

    アクションストリームによるリアクティブデータストリーム
    我々のアプリケーションのデータの一部は読み取り専用です.これは私たちにとって簡単になります.なぜなら、私たちは、観測可能なものを購読して、テンプレートにデータを表示し、それを一日と呼ぶだけです.他の回我々はユーザーがデータを変更したり、そのデータにアクションを取る能力をしたい.これらのユーザアクションを呼び出すことができますAction Streams . 我々は、アクションストリームをRxjs科目を使用してストリームを作成し、それらのストリームに値を投げることができます.アクションストリームを取ることで、我々のデータストリームは、それらのアクションに反応し、RXJS演算子を活用してデータを変更することができます.以下を示すアクションストリームを宣言する例を示しますselectedUser .
    private selectedUserSubject = new BehaviorSubject<number>(null);
      selectedUserAction$ = this.selectedUserSubject.asObservable();
      onSelectedUser(id) {
        this.selectedUserSubject.next(id);
      }
    
    これを壊すために、我々は数とその観察可能な対応を発する我々のBehaviorsubjectを持ちます.次に、コンポーネントから呼び出されたときに選択されたユーザーのIDをそのアクションストリームに出力するヘルパーメソッドを持ちます.この情報をallUser$ データストリームは、選択したユーザーを解放し、ユーザーのアクションに反応するストリームを作成できます.
    selectedUserData$: Observable<User> = combineLatest([
        this.allUser$,
        this.selectedUserAction$
      ]).pipe(
        map(([allUsers, selectedUser]) => allUsers.find(u => u.id === selectedUser))
      );
    
    私たちはselectedUserData$ の結果であるプロパティcombineLatest 演算子.これは、両方のストリームから出力される最後の値を受け取り、その値を配列として返します.での配列の破壊map 演算子は、結果を返しますallUsers array find関数.だから今、我々はアクションストリームに新しいIDを発行するたびに、このパイプは私たちに新しいユーザーを返します.
    周りの貼り付けのおかげ!私はあなたが何かヒントや物事を私は私に知らせてください改善することができる場合は、もっと書くことを試みている!