2016-08-17 11 views
0

コールバック関数を登録するコンポーネントとAngularサービスで 'データ要求オブジェクト'を持つAngularアプリケーションを設計しようとしています。このサービスは基本的に、すべてのデータ要求オブジェクトとそれらが参照するコールバック関数を追跡します。次に、長いポーリングを実行して、RESTful APIへの非同期呼び出しを行います。すべてのデータが入ってくると、サービスはAPIコールの結果を使って、どのコンポーネントがどのデータを必要としているのかを判断します。複数のAPIデータサービスを持つアプリケーション

私の頭をラッピングするのに問題があるという問題は、各コンポーネントが特定の形式を規定したJSONオブジェクトにデータを変換する必要があることです。たとえば、グラフコンポーネントでは、データ結果が一方向に見えるだけでなく、データ結果が別の方法で表示される必要のあるテーブルコンポーネントが必要な場合があります。

さらに複雑にするために、コンポーネントが複数の異なるRESTful APIのデータに登録できるようにデータサービスを設計したいと考えています。

私はAngularにはかなり新しいので、このタイプのアプリケーションを達成するためのいくつかのベストプラクティスについて助けを求めたかったのです。私がやっていることは、私のコンポーネントが登録する「プライマリ」データサービスを持つことです。

{ 
    "service": "apiService", 
    "request": { 
     ... 
    } 
} 

次に、各RESTfulなAPIのための別の角度のサービスが存在します:登録機能は、引数としてコールバック関数などのような形式になりますデータリクエストオブジェクトをとります。これらのサブサービスは、データ要求オブジェクトの処理を処理し、上記の「サービス」フィールドに対応します。プライマリデータサービスは、長いポーリングサイクルで要求をサブサービスにキューイングします。 (:私はES6を使用しています。注):

class DataService { 
    constructor($q, $interval, $injector) { 
    this.$q = $q; 
    this.$interval = $interval; 
    this.$injector = $injector; 

    this.subscriptions = []; 
    this.callbacks = []; 

    this.poll(); 
    } 

    poll() { 
    let reqs = []; 
    angular.forEach(this.subscriptions, (sub, i) => { 
     let service = this.$injector.get(sub.service); 
     let deferred = this.$q.defer(); 

     reqs.push(deferred); 
     service.get(sub.request).then((result) => { 
      this.callbacks[i](result); 
      deferred.resolve(result); 
     }, (result) => { 
      deferred.reject(result); 
     }); 
    }); 

    this.$q.all(reqs).then(() => { 
     this.$interval(poll, this.pollInterval || 10000); 
    }); 
    } 

    register(request, callback) { 
    this.subscriptions.push(request); 
    this.callbacks.push(callback); 
    } 
} 

angular.module('DataService', []).service('DataService', DataService); 

私が実装する方法を考え出すトラブルを抱えています作品は、作品を「データ変換」ですので、プライマリ・データ・サービスは次のようになります。私の知る限り、このデータは変換ところ、私が見ることができる唯一の二つの場所が場所を取ることができ、実際にあります:

  1. 部品個々のAPIサービス

インサイド

  • 内の最初の道のdoesnコンポーネントはやや愚かでなければならないという共通の慣習を破るので、私にとって実行可能な選択肢のように思えます。コンポーネントは、RESTful APIが返すデータの変換を処理すべきではありません。データはそのまま使用する必要があります。

    しかし、2番目の方法では、それぞれのRESTful APIサービスが、作成したすべてのコンポーネントタイプの変換関数を持つ必要があるという別の問題も生じます。これはどういうわけか私には「きれい」ではないようです。

    この目標を達成するためにアプリケーションを設計できる別の方法はありますか?どんな洞察にも感謝します。

  • 答えて

    0

    角度のビルトインイベントシステムを使用するだけです。

    //Constructor 
    constructor($q, $interval, $injector, $rootScope) { 
    this.$q = $q; 
    this.$interval = $interval; 
    this.$injector = $injector; 
    this.$rootScope = $rootScope; 
    this.listeners = []; 
    //No idea how its written in Angular2 but cleanup the event listeners when this is destroyed 
    //Example in 1.5.x: 
    //$scope.$on('$destroy',() => angular.forEach(this.listeners, l => l()); 
    this.poll(); 
    } 
    
    //The new register method 
    register(ev, callback) { 
    //When cleaning up - iterate over listeners and invoke each destroy function - see constructor 
    this.listeners.push(this.$rootScope.$on(ev, callback)); 
    } 
    
    //The new poll method 
    poll() { 
        let reqs = []; 
        angular.forEach(this.subscriptions, (sub, i) => { 
         let service = this.$injector.get(sub.service); 
         let deferred = service.get(sub.request).then((response) => { 
         //responseToEventsMapper should map and parse response to list of events to fire. 
         //Lets say the response is an authentication response for login attempt, 
         //then the triggered events will be 'Auth:stateChange' and 'Auth:login' with 
         //response.user as data. configure responseToEventsMapper upfront. 
         let events = this.responseToEventsMapper(response); 
         angular.forEach(events, event => this.$rootScope.$emit(event.type, event.data)); 
         }); 
         reqs.push(deferred); 
        }); 
    
        this.$q.all(reqs).then(() => { 
         this.$interval(poll, this.pollInterval || 10000); 
        }); 
        } 
    
    +0

    チップをありがとう。私はあなたが$ emitと$をこの方法で使用することができなかったことを認識しませんでした(または、$で返された登録解除関数、特に便利です)。 responseToEventsMapperのために、私の質問はまだマッパーがサービスで定義されるべきかコンポーネントの中で定義されるべきですか? apiAとapiBの2つのAPIがあるとします。彼らはどちらも、全く異なるフォーマット、jsonAとjsonBで応答を返します。しかし、このコンポーネントでは、データが異なる形式であることが必要です(jsonC)。responseToEventsMapperはこの変換を実行する必要がありますが、適切な場所はどこに定義されていますか? – snusnu

    +0

    登録フェーズでは、各加入者に独自のマッパーを提供できます。 –

    関連する問題