2017-01-19 13 views
0

私たちはサービスを持っています。AccountServiceと呼ばれ、getAccounts(customerId)というメソッドを公開しています。角度サービスの約束を解決する

その実装では、$ http GET要求を起動し、呼び出し元のコントローラに約束を返し、返されたアカウントの配列を解決したらコントローラのスコープに配置します。簡略図で

はすべて以下のようになります。

// The service 
.factory('AccountService', ['$http', function($http) { 
    var _getAccounts = function(customerId) { 
     var request = { 
      'method': 'GET', 
      'url': 'http://localhost:8081/accounts/' + customerId 
     }; 
     return $(request); 
    }; 

    return { 
     getAccounts: _getAccounts 
    }; 
}]); 

// Inside the conntroller 
AccountService.getAccounts($scope.customerId) 
    .then(function(response) { 
     $scope.accounts = response.data; 
    }); 

だから、約束は、コントローラのスコープは、アカウントのリストが取り込まれます解決されます一度。

私は上記のコードを私の問題が何であるかというアイデアを得るために単純なものにしていましたが、実際には例外を処理するコード、ウォッチャーをリフレッシュするコードなどです。

私の問題は、このAccountServiceがたくさんのコントローラから使用されていることと、これらすべての見通しで約束を解決することは、このボイラープレートリゾルバコードをすべて繰り返すだけでなく、私がr /すべての単一コントローラテストで成功シナリオと例外シナリオの両方をテストします。

私の質問は: サービスの約束を解決し、約束を返すのではなく、応答を返すよい方法がありますか?

私はAngularとJSの非常に初心者ですので、私の質問が素朴に見える場合は優しくしてください。私はJavaの経験のヒープを持っていると私の心は、ケースではないかもしれないどこでもようにJavaに行くようです。

は、あなたが、一度あなたの$httpは、データをフェッチして行われるように設計し、あなたの工場の変数(ややキャッシュ)に保存することができ、その後の工場コールにご入力のために事前に

答えて

0

は、サービス内の約束を解決し、コントローラではなく、約束に応答を返すために良い方法はありますか?

私の意見では、いいえ、ありません。これは、非同期呼び出しが動作する方法にまで沸きます。コールバックを渡すか、何も返されないか、コールバックを渡さずにメソッドは通知されるオブジェクト(約束)を返します。いくつかの回避策があるかもしれませんが、私はそれがそれより良いとは思わない。

部分的に定型文を減らす1つの方法は、サービスでcatchを使用し、代わりに返されるpromiseを返すことです。

には、以下の非常に簡単な例を考えてみましょう:

angular.module('myApp') 
    .factory('NetworkRequests', [ 
    function() { 
     var _getData = function() { 
     var promise = new Promise((resolve, reject) => { 
      var a = true, 
       data = ['a', 'b', 'c']; 

      if (a) { 
      resolve(data); 
      } else { 
      reject('Rejection reason: ...'); 
      } 
     }); 

     return promise.catch((error) => { 
      // Notify some error handling service etc. 
      console.log(error); 
      return []; 
     }); 
     }; 

     return { 
     getData: _getData 
     }; 
    } 
    ]);  

約束変数は、あなたのhttpリクエストの結果だろう。コントローラーコンテキスト(例えば、空の配列)で意味をなさないcatch関数でいくつかのデータを返さなければなりません。そして、あなたは、コントローラのエラー処理を気にする必要はありません。

再び
angular.module('myApp') 
    .controller('DataController', ['NetworkRequests', 
    function(NetworkRequests) { 
     NetworkRequests.getData().then((data) => { 
     this.data = data; 
     }); 
    } 
    ]); 

を、これは完全な問題を解決していませんが、少なくとも一部のエラー処理は、サービス中にカプセル化することができます。

+0

はい、私は非同期のものを同期させるのが良い考えではないと思います。再び、私は、java.util.concurrent.Future'が完了するまでスレッドをブロックできるJavaの考え方を混乱させました。 – Julian

0

をありがとうキャッシュにそのようなデータがあるかどうかをチェックします。はいの場合はキャッシュデータを返し、それ以外の場合は$http呼び出しを呼び出します。ここで

はコードです:ここでは

.factory('AccountService', ['$http', '$q', function($http, $q) { 
    var cachedData = null; 
    var defered = $q.defer(); //create our own defered object 
    var _getAccounts = function(customerId) { 
    if (cachedData !== null) { 
     console.log('get from cachedData') 
     defered.resolve(cachedData); // resolve it so that the data is passed outside 
     return defered.promise; //return your own promise if cached data is found 
    } else { 
     var request = { 
     'method': 'GET', 
     'url': 'mockdata.json' 
     }; 
     return $http(request).then((response) => { //return a normal $http promise if it is not. 
     console.log('get from $http'); 
     cachedData = response.data; 
     return cachedData; 
     }); 
    } 
    }; 

    return { 
    getAccounts: _getAccounts 
    }; 
}]); 

working plnkrです。コンソールを開き、GetDataボタンをクリックします。初めてget from $httpを記録すると表示されます。その後の呼び出しではget from cachedDataが記録されます。

+0

これが私に求められているかどうかはわかりません。あなたはまだ私が避けようとしているものであるコントローラの約束を解決します。あなたのコード 'AccountService.getAccounts()。then(...)' – Julian

+0

@Julianを使用して、約束を解決する必要があります。それ以外の場合は、getAccounts()の戻り値の型が異なります。あなたの目標が '.then'の使用を避けることであるなら、それは別の話です。 – CozyAzure

0

1つの方法は、オブジェクトを再利用してデータで埋め込むことです。これはngResourceによって使用されます。

それは

var data = []; 

function getAccounts(customerId) { 
    var promise = $http(...).then((response) => { 
     Object.assign(promise.data, response.data) 
    }); 

    promise.data = []; 

    return promise; 
}; 

データが$scope.accounts = AccountService.getAccounts(...).dataとして結合に利用可能であるようなものです。明白な欠点は、アンロードされたコンテンツのスプラッシュがあることです。

もう1つの方法は、あなたが言及したものです。最も頻繁に使用されています。コントローラーのWETコードに問題がある場合は、WETコードをクラス継承で削除し、動作の仕方を変更することではなく、処理する必要があります。

さらに別の方法が推奨されます。ルータとルート/ステートリゾルバを使用すると、非同期にロードされるデータが不要になります。リゾルバで解決されたデータは、配列としてルートテンプレートに注入されます。あなたの元の質問に答えるために

関連する問題