2017-09-24 27 views
0

私はかなり角度のあるシーンに新しいです、そして、私はいくつかの予期しない振る舞いから私の髪を引っ張り出しています。角度 - サービスのオブザーバー

私は、このコールがルートからページロードで2回実行されている方法を停止することができます

queryList(): Observable<ApiList[]> { 
    if(this.loadingApiList == true) { 
     return Observable.of(this.queryListResult); 
    } 
    this.loadingApiList = true; 
    return this._http 
     .get('samples/apiList.json').map((response: Response) => <ApiList[]> response.json()) 
     .do(data => { 
     this.queryListResult = data; 
     }); 
} 

私IntegrationsServiceに次のコードを持っていますか?

コンポーネントは、このメソッドを呼び出し、ナビゲーション中にリストを作成し、また、別のコンポーネントには、以下の方法で同じサービスを呼び出します。

getApiName(IT_ID:number) { 
    console.log(this.queryListResult); 
    let obj = this.queryListResult.find(o => o.IT_ID == IT_ID); 
    if(obj) { 
     return obj.IT_Name; 
    } 
    return false; 
} 

私が使用したときに、私はしかし、ルートを使用していないとき、これは完璧に動作しますルートのgetApiNameは未定義の結果を返します。

解決オブジェクトも使用しましたが、問題は解決しましたが、jsonファイルに2つの呼び出しが行われました。これは私が使用したものです。

resolve(route: ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<any>{ 
    return this._service.queryList() // We need this to finish first. 
    } 

は、私は本当に今こだわって - 私はそれが決意を使用して作業を取得することができますが、それは.jsonを2回呼び出しを持つ無駄です。

これを行う正しい方法は何ですか?

+0

フラグを設定しても、操作が完了してクエリリストの結果が割り当てられているとは限りません。これを達成する1つの方法は、データを被験者ベースの観測可能なものに暴露し、フェッチを一度トリガすることである。 https://blog.jonrshar.pe/2017/Apr/09/async-angular-data.htmlここでは、このパターンをどのように使用したかを示します。 – jonrsharpe

答えて

1

ルートからのページロードでこのコールが2回実行されるのを止める方法を教えてください。

これは、2回購読しているために発生しています。観測可能なオブジェクトは怠惰で、.subscribe()で呼び出すたびに実行が開始されます。あなたの場合は、ネットワーク要求がトリガーされます。オブザーバブルの.subscribe()は、.call()、または単に関数の場合は()と考えることができます。関数を呼び出すたびに、その関数が実行されます。

これを念頭に置いて、発生する動作が予想されます。これを解決するにはさまざまな方法がありますが、類似していますが、ユースケースに応じて少し異なります。すなわち、購読と購読解除の正確なタイミング。一般に、あなたが探しているのはmulticastingです。

最も単純な形式のマルチキャストは、the .shared() operatorを使用しています。 official docsより。しかし強調(私を)注意:

はマルチキャスト(株)元観測可能な、新しい観測を返します。 少なくとも1つのサブスクライバが存在する限り、このオブザーバブルはサブスクライブされ、データを送信します。すべての加入者が登録を解除すると、Observableソースから退会します。 Observableはマルチキャストであるため、ストリームをホットにします。これは.publish().refCount()の別名です。

BehvaiorSubjectの作成に興味があるのは、「現在の値」という概念です。 API呼び出しは何も返しません。単にリクエストをトリガーします。ここで

は、概念実証です:

export class Service { 

    public data$ = new BehaviorSubject(null); 

    public get() { 
    this.http.get(`some/data`).subscribe(data => this.data$.next(data)) 
    } 

} 

nulldata$に加入したときに、すべての加入者が同期取得する値です。このように使うことができます。

もちろん
this.get() 
this.data$.subscribe(data => /* ... */) 

、あなたがよりよいものにこれをラップし、さらにキャッシュのようなものを実装を開始することができ、など


いくつかの便利なリンク:

+0

詳細な回答ありがとうございます。 BehaviorSubjectを使用しないと、get()を呼び出す各コンポーネントのために2つの要求が発生する同じ問題が発生しますか? – Colin

+0

真実なので、私が言ったのは、ここで与えた設定は、 'BehaviorSubject'を理解する出発点に過ぎません。その考え方は、エンドポイントをカスタムロジックで呼び出す頻度を処理する必要があるということです。データが古くなる可能性があるため、_never_で再度呼び出すことは望ましくありません。 RxJSの観点から見ると、あなたが作る2つの呼び出しは異なる結果になるかもしれないことは分かっています。何らかの形でレスポンスをキャッシュし、応答が有効であるかどうかを判断するのはあなた次第です。 –

+0

サービスのngOnInitでget()を呼び出して、データが存在していることを確認していれば、明らかです。このget()の前に登録されたすべてのコンポーネントは、購読を使用して利用可能なときに更新されたデータのコピーを受け取りますか? – Colin