バックエンドにAJAXリクエストを行っているサービスがあります
サービス:
function GetCompaniesService(options)
{
this.url = '/company';
this.Companies = undefined;
this.CompaniesPromise = $http.get(this.url);
}
コントローラ:
var CompaniesOb = new GetCompanies();
CompaniesOb.CompaniesPromise.then(function(data){
$scope.Companies = data;
});
「.then」関数をコントローラーで処理するのではなく、サービスで処理したいのですが、サービス内のプロミスが解決された後、コントローラーがサービスからのデータに作用できるようにしたいと考えています。
基本的に、私はそのようなデータにアクセスできるようにしたいです:
var CompaniesOb = new GetCompanies();
$scope.Companies = CompaniesOb.Companies;
サービス自体の内部で取り扱われる約束の解決。
これは可能ですか?それとも、そのプロミスの解決策にアクセスできる唯一の方法は、サービスの外部からですか?
サービス自体で$http
の応答を処理するだけの場合は、次のように、then
関数をサービスに追加して、return
関数からthen
よりも多くの処理を行うことができます。
function GetCompaniesService(options) {
this.url = '/company';
this.Companies = undefined;
this.CompaniesPromise = $http.get(this.url).then(function(response) {
/* handle response then */
return response
})
}
ただし、コントローラーでプロミスを使用することはできますが、返されるものはすでにサービスで処理されています。
var CompaniesOb = new GetCompanies();
CompaniesOb.CompaniesPromise.then(function(dataAlreadyHandledInService) {
$scope.Companies = dataAlreadyHandledInService;
});
それを達成するのに問題はありません!
あなたが心に留めておかなければならない主なことは、あなたはあなたのサービスで同じオブジェクト参照を保持しなければならないということです(そしてJavaScript配列ではオブジェクトです)。
シンプルなHTMLは次のとおりです。
<div ng-controller = "companiesCtrl">
<ul ng-repeat="company in companies">
<li>{{company}}</li>
</ul>
</div>
これがサービスの実装です。
serviceDataCaching.service('companiesSrv', ['$timeout', function($timeout){
var self = this;
var httpResult = [
'company 1',
'company 2',
'company 3'
];
this.companies = ['preloaded company'];
this.getCompanies = function() {
// we simulate an async operation
return $timeout(function(){
// keep the array object reference!!
self.companies.splice(0, self.companies.length);
// if you use the following code:
// self.companies = [];
// the controller will loose the reference to the array object as we are creating an new one
// as a result it will no longer get the changes made here!
for(var i=0; i< httpResult.length; i++){
self.companies.Push(httpResult[i]);
}
return self.companies;
}, 3000);
}}]);
そして最後に、あなたが望む通りのコントローラー:
serviceDataCaching.controller('companiesCtrl', function ($scope, companiesSrv) {
$scope.companies = companiesSrv.companies;
companiesSrv.getCompanies();
});
説明
上記のように、コツはサービスとコントローラー間の参照を維持することです。これを尊重したら、コントローラースコープをサービスのパブリックプロパティに完全にバインドできます。
コードのコメントで、機能しない部分のコメントを外してみると、コントローラーが参照を失っていることがわかります。実際、コントローラーは古いアレイへの参照を保持し続けますが、サービスは新しいアレイを変更します。
最後にもう1つ重要なことは、$ timeoutがrootSCopeで$ apply()をトリガーしていることを覚えておいてください。これが、コントローラースコープが「単独」で更新される理由です。これがない場合、通常のsetTimeout()に置き換えようとすると、コントローラーが会社リストを更新していないことがわかります。これを回避するには、次の方法があります。
お役に立てれば!