コマンド式からレスポンス式(六)まで


このシリーズの第一章から第五章まで、rxjsの応答式プログラミングに基づく基礎知識は基本的に紹介されました.もちろんScheduler、behaviorSubject、replaySubjectなど多くの知識点は言及されていません.この章から反応式をanglarの大きな環境において、実際のプロジェクトでどうやって使うかを確認します.もちろんこれらは個人の使用中の経験です.
また、この章から始まるコードの例は一部の断片だけかもしれません.または考え、正式に実行するには、コードを正しい環境に入れる必要があります.
アングラーの応答式インターフェースはどこにもありません.
アングラーにrxjsが内蔵されている以上、応答式の影を見つけられるところが多くなければなりません.
Activated Route-ルーティング上の情報、例えば伝達パラメータなどを取得するためによく使われます.
export interface ActivatedRoute {
    url: Observable
    params: Observable;
    queryParams: Observable;
    fragment: Observable;
    data: Observable;
    get paramMap: Observable;
    get queryParamMap: Observable;
    toString(): string;
}
AbstractControl-FormControlの基質、特に応答式フォームの中で、あなたはきっとそれを見たことがあります.
export abstract class AbstractControl {
    get valueChanges: Observable;
    get statusChanges: Observable;
}
Http-これは言うまでもなく、Http通信を使うプロジェクトはそれから離れています.
export class Http {
    get(url: string, options?: RequestOptionsArgs): Observable;
    post(url: string, body: any, options?: RequestOptionsArgs): Observable;
    head(url: string, options?: RequestOptionsArgs): Observable;
}
EventEmitter-コンポーネントが外にデータを送る時、きっと使ったことがありますよね?
export class EventEmitter extends Subject {
    subscribe(generatorOrNext?: any, error?: any, complete?: any): any;
}
Observableは見つかりませんでしたか?よく見ると、Subjectから継承されていますが、Subjectは?続きを見る:
export declare class Subject extends Observable implements ISubscription {
    ...  
}
Subjectは最終的にObservableから引き継がれます.もちろん他にもたくさんありますが、とにかく応答式の世界ではeverthing is Observableを覚えてください.
応答式のコンポーネントを構築する
入力と出力はプログラミング中のどこにでもあります.相互作用のあるものに触れると、入力と出力に抽象的になります.
一番はっきりしているのは、@Inputと@Outputを使っている時です.きっと入出力と付き合っているのです.componentを定義するクラスを一部と見なすと、templateに伝達されるデータも一種の出力と考えられ、各serviceから取得したデータも一つのデータとして入力することができます.この考えに基づいて、一つのコンポーネントはデータとテンプレートを接続するブリッジであると考えられます.一番重要な機能はサービス中のデータを入力としてテンプレートに出力することです.もちろん、テンプレートから発生したデータを入力としてサービスに出力することもできます.そこで私たちはこのようなコンポーネントを抽象的に出すことができます.
export abstract class BaseComponent {

    abstract subscription$$: Subscription; //                      。

    abstract launch(option?: any): void;  //        

    abstract initialModel(option?: any): void; //           
}
  • initial Modelのすべてのコンポーネントで使用するデータはこの方法で得られ、データの使用者に配布される.
  • launchのすべてのコンポーネントでサービスに転送する必要があるデータは、この方法で外部に転送されます.
  • subscription$は、実際のプロジェクトでは、いくつかのストリームを手動で購読することを避けることができません.いくつかのストリームは、私たちが手動でリリースする必要があります.この変数は全体的に責任を負い、その初期化は基本的にlaunch方法に固定されます.
  • 私たちは画像認証コードを持つ登録機能を実現する必要があると仮定して、そのデータのインタラクションを実現します.
    @Component({
        ...
    })
    export class LoginComponent extends BaseComponent implements OnInit, OnDestroy {
        subscription$$: Subscription;
    
        randomCode: Observable; //    ,         
    
        generateCode$: Subject = new Subject(); //      ,             。
    
        //             ,              ,  : { username: string; password: string; randomCode: string};                。
        login$: Subject = new Subject();
    
        constructor(private auth: AuthService) { } //         
    
        ngOnInit() {
            this.initialModel();
    
            this.launch();
    
            this.goTo(); //            。
        }
    
        initialModel() {
            this.randomCode = this.auth.getRandomCode();
        }
    
        launch() {
            this.subscription = this.auth.login(this.login$)
                .add(this.auth.generateRandomCode(this.generateCode$));
        }
    
        goTo() {
            this.subscription.add(
                this.auth.isLoginSuccess().subscribe(success => {
                    //       。
                })
            )
        }
    
        ngOnDestroy {
            this.subscription$$.unsubscribe();
        }
    }
    
    以上のコードを読むことによって、私達の核心の注目点はinitial Modelとlaunchの二つの方法に置くだけでいいです.一つは私達にどのデータを取得したかを教えてくれます.一つはどのデータを出力したかを教えてくれます.また、ログイン動作と認証コードを取得する動作はコンポーネント初期化時にすでにサービスに教えられています.このコマンド式はまったく異なる2つのスタイルです.コマンドスタイルでは、ユーザーがログインボタンをクリックするまで、login関数を呼び出して、ログイン動作を開始します.サービスコードを見てみます.
    @Injectable()
    export class AuthService {
    
        login$: BehaviorSubject = new BehaviorSubject();
    
        constructor(private http: Http) { }
    
        login(data: Observable): Subscription {
            // url:    url; Response: angular    http    。
            return this.http.post(url)
                    .map((res: Response) => {
                    //             token,       BehaviorSubject       token;
                        const body = res.json();
    
                        return body.data.token;
                    })
                    .subscribe(this.login$);
        }
    
        generateRandomCode(signal: Observable): Observable {
            return this.http.get(url)
                .map((res: Response) => {
                    //        random    
                    const body = res.json();
    
                    return body.data.random;
                });
        }
    
        isLoginSuccess(): Observable {
            return this.login$.mapTo(true);
        }
    }
    
    最初に述べた考え方に基づいて、私達は基本的に応答式の風格に基づく登録コンポーネントの骨格を構築しました.基本的なコースが出てきました.しばらくここに来ます.まず、どの機能を拡張するかを考えてみてもいいです.例えば、30秒で一回の認証コードを交換し、ユーザーがクリックした時にすぐに認証コードを交換するなど、次の機能を続けます.