2016-04-10 12 views
3

JSON APIを呼び出してネストされたHTMLリスト(<ol>)にデータをロードするAngular 2アプリがあります。本質的に動的に生成されるツリービュー。 APIからのデータセットは最終的に非常に大きくなるので、ユーザーがブランチを開いたとき(ブランチを開き、開かれたノードのIDでAPIが呼び出されるとAPIはJSONを返します)ノードの直下の子のフィード、Angularは返されたJSONをいくつかの新しいHTML <li>要素にバインドし、ツリーを展開して新しいブランチを表示します)。Angular 2 APIドリブンツリービューで重複するHTTPリクエストを防止する

このPlunkrで実際に動作しています。それは再帰的な指示を使用し、うまく動作します。 現在、パブリックリクエストまで実際のAPIを開くことができないので、静的なJSONフィードを呼び出すだけです。したがって、各ノードの返されたデータはちょうど繰り返されますが、うまくいけばいいと思います。

私が今克服しようとしている問題は、ブランチを閉じてから再度開いたときに無関係なHTTPコールを防ぐことです。

getContentNodes() { 
    this._contentService.getContentNodes(this._startNodeId) 
     .distinctUntilChanged() 
     .subscribe(
      contentNodes => this.contentNodes = contentNodes, 
      error => this.errorMessage = <any>error 
     ); 
} 

しかし、私が開くとき、次のように私は、これは.distinctUntilChanged()方法はapp/content-list.component.tsファイルにチェーンにデータサービスに加入する方法を変更するような単純なものであろうと期待していたHTTP client docsを読みましたブラウザのネットワークインスペクタでは、同じツリーブランチが再度開かれるたびにAPIを呼び出します。

誰でもこの問題を解決する方法をアドバイスできますか?

多くのありがとうございます。

EDIT:

私は以下@Thierry TEMPLIERの答えを実装しようとしています。 APIによって返されたデータをキャッシュします。だから、コンテンツ・サービスは現在、次のとおりです。

import {Injectable}     from 'angular2/core'; 
import {Http, Response}    from 'angular2/http'; 
import {Headers, RequestOptions} from 'angular2/http'; 
import {ContentNode}    from './content-node'; 
import {Observable}     from 'rxjs/Observable'; 

@Injectable() 
export class ContentService { 
    constructor (private http: Http) {} 

    private _contentNodesUrl = 'app/content.json'; 

    _cachedData: ContentNode[]; 

    getContentNodes (parentId:number) { 
     if (this._cachedData) { 
      return Observable.of(this._cachedData); 
     } else { 
      return this.http.get(this._contentNodesUrl + parentId) 
       .map(res => <ContentNode[]> res.json()) 
       .do(
        (data) => { 
        this._cachedData = data; 
       }) 
       .catch(this.handleError); 
     } 
    } 

    private handleError (error: Response) { 
     console.error(error); 
     return Observable.throw(error.json().error || 'Server error'); 
    } 
} 

しかし、何をここで起こっていることは、ページのロード時、this._cachedDataはfalseを返すと、API呼び出しが正しいれ、返される値(data)で焼成し、this._cachedDataを移入されていることです。ツリーのノードは、WebページのUIに開かれたときただし、次の行は、最終的には、ブラウザがクラッシュするまで繰り返し何千回も実行されます。

return Observable.of(this._cachedData); 

それは角度に来るとき、私は最初に、まだ非常によ2、なぜこれが私の学習を助けるために働いていないのかについての指針を本当に感謝するでしょう。

答えて

3

私は、次のアプローチを使用してノードごとにデータをキャッシュします:distinctUntilChanged

getData() { 
    if (this.cachedData) { 
    return Observable.of(this.cachedData); 
    } else { 
    return this.http.get(...) 
      .map(res => res.json()) 
      .do((data) => { 
      this.cachedData = data; 
      }); 
    } 
} 

「問題は、」あなたが同じデータフローを使用する必要があるということです。おかげ@Thierry

+0

:しかし、あなたは、異なるデータフロー上のいくつかの要求を実行するので、それは

...あなたの場合にはそうではないのですが、より詳細については、この質問を参照してください。明確にするために、サービスまたはコンポーネントにこれを置く必要がありますか? – Dan

+1

あなたは大歓迎です!はい、あなたのgetContentNodesメソッドであなたのサービス内にあります。 –

+0

ええと、私はこれを誤ってローカルでコンパイルするときに間違って実装したのかどうかはわかりませんが、UIのツリーノードの1つを開いてブラウザがクラッシュするとハングアップします。 Plunkrと同じです:http://plnkr.co/edit/Bi7buRtzczoiSyLPKoOh?p=preview – Dan

関連する問題