違いは何ですかService
、Provider
とFactory
AngularJSには?
service.factory
。この主題をさらに複雑にしたくなかった。
違いは何ですかService
、Provider
とFactory
AngularJSには?
service.factory
。この主題をさらに複雑にしたくなかった。
回答:
AngularJSメーリングリストから、サービス、ファクトリ、プロバイダー、およびそれらのインジェクションの使用法を説明する素晴らしいスレッドを受け取りました。答えをまとめる:
構文:module.service( 'serviceName', function );
結果:serviceNameを注入可能な引数として宣言すると、関数のインスタンスが提供されます。つまり new FunctionYouPassedToService()
。
構文:module.factory( 'factoryName', function );
結果:factoryNameを注入可能な引数として宣言すると、module.factoryに渡された関数参照を呼び出すことによって返される値が提供されます。
構文:module.provider( 'providerName', function );
結果:providerNameを注入可能な引数として宣言すると、が提供され (new ProviderFunction()).$get()
ます。コンストラクター関数は、$ getメソッドが呼び出される前にインスタンス化されますProviderFunction
。これは、module.providerに渡される関数参照です。
プロバイダーには、モジュール構成フェーズ中に構成できるという利点があります。
提供されているコードについては、こちらをご覧ください。
Miskoによるさらに詳しい説明は次のとおりです。
provide.value('a', 123);
function Controller(a) {
expect(a).toEqual(123);
}
この場合、インジェクターは値をそのまま返します。しかし、値を計算したい場合はどうでしょうか?次に、工場を使用します
provide.factory('b', function(a) {
return a*2;
});
function Controller(b) {
expect(b).toEqual(246);
}
そのfactory
ため、値を作成する機能があります。ファクトリ関数が他の依存関係を要求できることに注意してください。
しかし、もっとオブジェクト指向になり、Greeterと呼ばれるクラスが必要な場合はどうでしょうか。
function Greeter(a) {
this.greet = function() {
return 'Hello ' + a;
}
}
次に、インスタンス化するには、次のように記述する必要があります
provide.factory('greeter', function(a) {
return new Greeter(a);
});
次に、このようにコントローラで「挨拶」を求めることができます
function Controller(greeter) {
expect(greeter instanceof Greeter).toBe(true);
expect(greeter.greet()).toEqual('Hello 123');
}
しかし、それは言い過ぎです。これを書く短い方法はprovider.service('greeter', Greeter);
しかしGreeter
、インジェクションの前にクラスを構成したい場合はどうでしょうか?次に、
provide.provider('greeter2', function() {
var salutation = 'Hello';
this.setSalutation = function(s) {
salutation = s;
}
function Greeter(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}
this.$get = function(a) {
return new Greeter(a);
};
});
次に、これを行うことができます:
angular.module('abc', []).config(function(greeter2Provider) {
greeter2Provider.setSalutation('Halo');
});
function Controller(greeter2) {
expect(greeter2.greet()).toEqual('Halo 123');
}
注意点として、service
、factory
、およびvalue
すべてのプロバイダから派生しています。
provider.service = function(name, Class) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.instantiate(Class);
};
});
}
provider.factory = function(name, factory) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.invoke(factory);
};
});
}
provider.value = function(name, value) {
provider.factory(name, function() {
return value;
});
};
toEqual
とgreeter.Greet
は何かを理解しようとして迷う。もう少し現実的で親しみやすいものを使ってみませんか?
factory
/ service
/ / provider
:var myApp = angular.module('myApp', []);
//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
//provider style, full blown, configurable version
myApp.provider('helloWorld', function() {
this.name = 'Default';
this.$get = function() {
var name = this.name;
return {
sayHello: function() {
return "Hello, " + name + "!";
}
}
};
this.setName = function(name) {
this.name = name;
};
});
//hey, we can configure a provider!
myApp.config(function(helloWorldProvider){
helloWorldProvider.setName('World');
});
function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
$scope.hellos = [
helloWorld.sayHello(),
helloWorldFromFactory.sayHello(),
helloWorldFromService.sayHello()];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
{{hellos}}
</div>
</body>
this
コンテキストを変更しません$get
か?-その関数でインスタンス化されたプロバイダーを参照しなくなりました。
this
実際に呼び出されるのはnew Provider()
。$ get()であるため、コンテキストは変更されません。ここProvider
で、関数はに渡されapp.provider
ます。つまり、それは$get()
構築されたのメソッドとして呼び出されているProvider
ので、例が示すようthis
に参照さProvider
れます。
Unknown provider: helloWorldProvider <- helloWorld
これをローカルで実行するとなぜ取得されるのですか?コメントアウト、他の2つの例と同じエラー。非表示のプロバイダー構成はありますか?(Angular 1.0.8)-見つかりました:stackoverflow.com/questions/12339272/…–
TL; DR
1)あなたが使用している工場を、あなたがオブジェクトを作成し、その同じオブジェクトを返し、それにプロパティを追加します。このファクトリーをコントローラーに渡すと、オブジェクトのこれらのプロパティは、ファクトリーを通じてそのコントローラーで使用できるようになります。
app.controller(‘myFactoryCtrl’, function($scope, myFactory){
$scope.artist = myFactory.getArtist();
});
app.factory(‘myFactory’, function(){
var _artist = ‘Shakira’;
var service = {};
service.getArtist = function(){
return _artist;
}
return service;
});
2)Serviceを使用している場合、AngularJSは「new」キーワードを使用して、サービスをバックグラウンドでインスタンス化します。そのため、プロパティを「this」に追加すると、サービスは「this」を返します。サービスをコントローラーに渡すと、「this」のこれらのプロパティは、サービスを通じてそのコントローラーで使用できるようになります。
app.controller(‘myServiceCtrl’, function($scope, myService){
$scope.artist = myService.getArtist();
});
app.service(‘myService’, function(){
var _artist = ‘Nelly’;
this.getArtist = function(){
return _artist;
}
});
3) プロバイダーは、.config()関数に渡すことができる唯一のサービスです。サービスオブジェクトを使用可能にする前に、サービスオブジェクトのモジュール全体の構成を提供する場合は、プロバイダーを使用します。
app.controller(‘myProvider’, function($scope, myProvider){
$scope.artist = myProvider.getArtist();
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
app.provider(‘myProvider’, function(){
//Only the next two lines are available in the app.config()
this._artist = ‘’;
this.thingFromConfig = ‘’;
this.$get = function(){
var that = this;
return {
getArtist: function(){
return that._artist;
},
thingOnConfig: that.thingFromConfig
}
}
});
app.config(function(myProviderProvider){
myProviderProvider.thingFromConfig = ‘This was set in config’;
});
非TL; DR
1)ファクトリファクトリ
は、サービスを作成および構成する最も一般的な方法です。TL; DRが言った以上のことは本当にありません。オブジェクトを作成し、それにプロパティを追加して、同じオブジェクトを返すだけです。次に、ファクトリをコントローラーに渡すと、オブジェクトのこれらのプロパティは、ファクトリを介してそのコントローラーで使用できるようになります。より広範な例を以下に示します。
app.factory(‘myFactory’, function(){
var service = {};
return service;
});
これで、「myFactory」をコントローラーに渡すと、「service」にアタッチしたすべてのプロパティを使用できるようになります。
次に、いくつかの「プライベート」変数をコールバック関数に追加しましょう。これらはコントローラーから直接アクセスできませんが、必要に応じてこれらの「プライベート」変数を変更できるように、最終的に「サービス」にいくつかのゲッター/セッターメソッドを設定します。
app.factory(‘myFactory’, function($http, $q){
var service = {};
var baseUrl = ‘https://itunes.apple.com/search?term=’;
var _artist = ‘’;
var _finalUrl = ‘’;
var makeUrl = function(){
_artist = _artist.split(‘ ‘).join(‘+’);
_finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
return _finalUrl
}
return service;
});
ここで、これらの変数/関数を「サービス」にアタッチしていないことに気づくでしょう。後で使用または変更するために、単に作成しています。
ヘルパー/プライベート変数と関数が用意できたので、「サービス」オブジェクトにいくつかのプロパティを追加しましょう。「サービス」に設定したものは、「myFactory」を渡すどのコントローラー内でも直接使用できます。
アーティストを返すか設定するだけのsetArtistメソッドとgetArtistメソッドを作成します。また、作成したURLでiTunes APIを呼び出すメソッドを作成します。このメソッドは、iTunes APIからデータが返されると満たされるpromiseを返します。AngularJSでpromiseを使用した経験があまりない場合は、promiseについて詳しく説明することを強くお勧めします。
以下のsetArtistはアーティストを受け入れ、アーティストを設定できます。getArtistはアーティストを返します。callItunesは、最初にmakeUrl()を呼び出して、$ httpリクエストで使用するURLを作成します。次に、promiseオブジェクトを設定し、最終的なURLを使用して$ httpリクエストを作成します。$ httpはpromiseを返すため、リクエストの後に.successまたは.errorを呼び出すことができます。その後、iTunesデータで約束を解決するか、「エラーが発生しました」というメッセージで拒否します。
app.factory('myFactory', function($http, $q){
var service = {};
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
service.setArtist = function(artist){
_artist = artist;
}
service.getArtist = function(){
return _artist;
}
service.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
return service;
});
これで工場が完成しました。これで 'myFactory'を任意のコントローラーに挿入できるようになり、サービスオブジェクト(setArtist、getArtist、callItunes)にアタッチしたメソッドを呼び出すことができるようになります。
app.controller('myFactoryCtrl', function($scope, myFactory){
$scope.data = {};
$scope.updateArtist = function(){
myFactory.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myFactory.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
上記のコントローラーでは、「myFactory」サービスに注入しています。次に、「myFactory」からのデータを使用して$ scopeオブジェクトにプロパティを設定します。上記の唯一のトリッキーなコードは、これまでに約束を扱ったことがない場合です。callItunesがpromiseを返すため、.then()メソッドを使用して、iTunesデータでpromiseが満たされた場合にのみ$ scope.data.artistDataを設定できます。コントローラーが非常に「薄い」ことに気づくでしょう(これは優れたコーディング慣行です)。ロジックと永続データはすべて、コントローラーではなくサービスにあります。
2)サービス
おそらく、サービスの作成を処理する際に知っておくべき最大のことは、「新しい」キーワードでインスタンス化されるということです。JavaScriptの達人にとって、これはコードの性質に大きなヒントを与えるはずです。JavaScriptのバックグラウンドが限られている方や、「新しい」キーワードの実際の動作に慣れていない方のために、最終的にサービスの性質を理解するのに役立つJavaScriptの基礎を復習しましょう。
「new」キーワードを使用して関数を呼び出したときに発生する変更を実際に確認するには、関数を作成して「new」キーワードを使用して呼び出します。次に、「new」キーワードを検出したときにインタープリターが何を行うかを見てみましょう。最終結果はどちらも同じになります。
まず、コンストラクタを作成しましょう。
var Person = function(name, age){
this.name = name;
this.age = age;
}
これは、典型的なJavaScriptコンストラクター関数です。これで、「new」キーワードを使用してPerson関数を呼び出すたびに、「this」が新しく作成されたオブジェクトにバインドされます。
次に、Personのプロトタイプにメソッドを追加して、Personの「クラス」のすべてのインスタンスで使用できるようにします。
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
ここで、sayName関数をプロトタイプに配置したので、PersonのすべてのインスタンスはsayName関数を呼び出して、そのインスタンスの名前を警告することができます。
Personコンストラクター関数とsayName関数がそのプロトタイプにあるので、実際にPersonのインスタンスを作成してから、sayName関数を呼び出します。
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
したがって、Personコンストラクターを作成し、そのプロトタイプに関数を追加し、Personインスタンスを作成し、そのプロトタイプで関数を呼び出すためのコードはすべて、次のようになります。
var Person = function(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
次に、JavaScriptで「new」キーワードを使用したときに実際に何が起こっているかを見てみましょう。最初に気づくべきことは、この例で「new」を使用した後、まるでオブジェクトであるかのように、「tyler」でメソッド(sayName)を呼び出すことができるということです。したがって、最初に、Personコンストラクターがオブジェクトを返していることがわかります。コードでそれを確認できるかどうかは関係ありません。次に、sayName関数は直接Personインスタンスではなくプロトタイプにあるため、Person関数が返すオブジェクトは、ルックアップが失敗したときにそのプロトタイプに委任されている必要があります。より簡単に言えば、tyler.sayName()を呼び出すと、インタープリターは「OK、先ほど作成した 'tyler'オブジェクトを見て、sayName関数を見つけて呼び出します。ちょっと待ってください、ここには表示されません。表示されるのは名前と年齢だけです。プロトタイプを確認させてください。うん、それはプロトタイプにあるように見えます。私はそれを呼ばせてください。」
以下は、「new」キーワードが実際にJavaScriptで何をしているのかを考える方法のコードです。基本的には、上記の段落のコード例です。「インタープリタービュー」、つまりインタープリターがコードをノート内に表示する方法を示しました。
var Person = function(name, age){
//The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
//var obj = Object.create(Person.prototype);
//The line directly below this sets ‘this’ to the newly created object
//this = obj;
this.name = name;
this.age = age;
//return this;
}
これで、JavaScriptで「新しい」キーワードが実際に何を行うかについての知識が得られたので、AngularJSでサービスを作成する方が理解しやすいはずです。
サービスを作成するときに理解する最大のことは、サービスが「新しい」キーワードでインスタンス化されることを知ることです。この知識と上記の例を組み合わせると、プロパティとメソッドを「this」に直接アタッチし、サービス自体から返されることを認識できるはずです。これを実際に見てみましょう。
最初にFactoryの例で行ったのとは異なり、オブジェクトを作成してからそのオブジェクトを返す必要はありません。これまでに何度も言及したように、「new」キーワードを使用してインタープリターがそのオブジェクトを作成し、デリゲートするようにしているためです。これはプロトタイプであり、作業を行わなくても返却できます。
最初に、「プライベート」ヘルパー関数を作成しましょう。私たちの工場でもまったく同じことをしたので、これは非常に見覚えがあるはずです。ここでは各行が何をするかについては説明しません。工場の例でそれを行ったからです。混乱している場合は、工場の例をもう一度読んでください。
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
});
ここで、コントローラーで使用できるすべてのメソッドを「this」にアタッチします。
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.setArtist = function(artist){
_artist = artist;
}
this.getArtist = function(){
return _artist;
}
this.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
});
これで、ファクトリと同様に、setServiceist、getArtist、およびcallItunesは、myServiceを渡すどのコントローラーでも使用できるようになります。これがmyServiceコントローラーです(これは、出荷時のコントローラーとほぼ同じです)。
app.controller('myServiceCtrl', function($scope, myService){
$scope.data = {};
$scope.updateArtist = function(){
myService.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myService.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
前に述べたように、「新しい」機能が本当に理解できたら、サービスはAngularJSのファクトリーとほとんど同じです。
3)プロバイダー
プロバイダーについて覚えておくべき最大のことは、プロバイダーがアプリケーションのapp.config部分に渡すことができる唯一のサービスであることです。これは、サービスオブジェクトの一部をアプリケーションのほかの場所で使用できるようにする前に変更する必要がある場合に非常に重要です。サービス/工場と非常に似ていますが、これから説明するいくつかの違いがあります。
まず、サービスとファクトリーで行ったのと同じ方法でプロバイダーをセットアップします。以下の変数は、「プライベート」およびヘルパー関数です。
app.provider('myProvider', function(){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
//Going to set this property on the config function below.
this.thingFromConfig = ‘’;
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
}
*上記のコードのいずれかの部分が混乱を招く場合は、ファクトリーセクションをチェックして、すべての機能について詳しく説明します。
プロバイダーは3つのセクションがあると考えることができます。最初のセクションは、後で変更/設定される「プライベート」変数/関数です(上記を参照)。2番目のセクションは、app.config関数で使用できる変数/関数です。したがって、他の場所で使用できるようになる前に変更することができます(これも上記に示されています)。これらの変数は「this」キーワードに付加する必要があることに注意することが重要です。この例では、app.configで変更できるのは「thingFromConfig」だけです。3番目のセクション(下に表示)は、「myProvider」サービスを特定のコントローラーに渡したときにコントローラーで使用できるすべての変数/関数です。
プロバイダーを使用してサービスを作成する場合、コントローラーで使用できるのは、$ get()関数から返されるプロパティ/メソッドのみです。以下のコードは$ getを 'this'に配置します(これは最終的にその関数から返されることがわかっています)。これで、$ get関数はコントローラーで使用できるようにするすべてのメソッド/プロパティを返します。これがコード例です。
this.$get = function($http, $q){
return {
callItunes: function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
},
setArtist: function(artist){
_artist = artist;
},
getArtist: function(){
return _artist;
},
thingOnConfig: this.thingFromConfig
}
}
完全なプロバイダーコードは次のようになります。
app.provider('myProvider', function(){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
//Going to set this property on the config function below
this.thingFromConfig = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.$get = function($http, $q){
return {
callItunes: function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
},
setArtist: function(artist){
_artist = artist;
},
getArtist: function(){
return _artist;
},
thingOnConfig: this.thingFromConfig
}
}
});
これで、ファクトリとServiceの場合と同様に、setArtist、getArtist、callItunesは、myProviderを渡すどのコントローラーでも使用できます。これがmyProviderコントローラーです(これは、ファクトリー/サービスコントローラーとほぼ同じです)。
app.controller('myProviderCtrl', function($scope, myProvider){
$scope.data = {};
$scope.updateArtist = function(){
myProvider.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myProvider.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
前述のように、プロバイダーを使用してサービスを作成するポイントは、最終的なオブジェクトがアプリケーションの残りの部分に渡される前に、app.config関数を介していくつかの変数を変更できるようにすることです。その例を見てみましょう。
app.config(function(myProviderProvider){
//Providers are the only service you can pass into app.config
myProviderProvider.thingFromConfig = 'This sentence was set in app.config. Providers are the only service that can be passed into config. Check out the code to see how it works';
});
これで、プロバイダーの「thingFromConfig」が空の文字列としてどのように表示されるかを確認できますが、それがDOMに表示されると、「この文は設定されました...」になります。
すべてのサービスはシングルトンです。アプリごとに1回インスタンス化されます。彼らはすることができ、あらゆるタイプのそれは原始的な、オブジェクトリテラル、関数、またはカスタムタイプのさえインスタンスであるかどうか、。
value
、factory
、service
、constant
、およびprovider
方法は、すべてのプロバイダです。彼らはインジェクターにサービスをインスタンス化する方法を教えます。
最も冗長で最も包括的なものは、プロバイダーレシピです。残りの4つのレシピタイプ-値、工場、サービスおよび定数は- プロバイダレシピの上部にだけ糖衣構文です。
アプリケーションの起動前に行う必要があるアプリケーション全体の構成用のAPIを公開する場合にのみ、プロバイダーレシピを使用する必要があります。これは通常、動作がアプリケーション間でわずかに異なる必要がある可能性がある再利用可能なサービスでのみ興味深いものです。
decorator
。AngularJSファクトリ、サービス、プロバイダーについて
これらはすべて、再利用可能なシングルトンオブジェクトを共有するために使用されます。アプリ/さまざまなコンポーネント/モジュール間で再利用可能なコードを共有するのに役立ちます。
ドキュメントサービス/ファクトリから:
- 遅延インスタンス化 – Angularは、アプリケーションコンポーネントが依存している場合にのみサービス/ファクトリをインスタンス化します。
- シングルトン –サービスに依存する各コンポーネントは、サービスファクトリによって生成された単一のインスタンスへの参照を取得します。
ファクトリは、オブジェクトを作成する前にロジックを操作/追加できる関数で、新しく作成されたオブジェクトが返されます。
app.factory('MyFactory', function() {
var serviceObj = {};
//creating an object with methods/functions or variables
serviceObj.myFunction = function() {
//TO DO:
};
//return that object
return serviceObj;
});
使用法
これは、クラスのような関数の単なるコレクションにすることができます。したがって、コントローラー/ファクトリー/ディレクティブ関数内に注入するときに、別のコントローラーでインスタンス化できます。アプリごとに1回だけインスタンス化されます。
単にサービスを見ながら、アレイのプロトタイプについて考えます。サービスは、「new」キーワードを使用して新しいオブジェクトをインスタンス化する関数です。this
キーワードを使用して、サービスオブジェクトにプロパティと関数を追加できます。ファクトリとは異なり、何も返しません(メソッド/プロパティを含むオブジェクトを返します)。
app.service('MyService', function() {
//directly binding events to this context
this.myServiceFunction = function() {
//TO DO:
};
});
使用法
アプリケーション全体で単一のオブジェクトを共有する必要がある場合に使用します。たとえば、認証されたユーザーの詳細、共有可能なメソッド/データ、ユーティリティ関数など。
プロバイダーは、構成可能なサービスオブジェクトを作成するために使用されます。設定機能からサービス設定を行うことができます。$get()
関数を使用して値を返します。$get
関数は、角度で実行フェーズで実行されます。
app.provider('configurableService', function() {
var name = '';
//this method can be be available at configuration time inside app.config.
this.setName = function(newName) {
name = newName;
};
this.$get = function() {
var getName = function() {
return name;
};
return {
getName: getName //exposed object to where it gets injected.
};
};
});
使用法
サービスオブジェクトを使用可能にする前に、モジュールごとの構成を提供する必要がある場合。のような環境に基づいてAPI URLを設定したいとしますdev
、stage
またはprod
注意
Angularの設定フェーズで利用できるのはプロバイダーのみですが、サービスとファクトリーでは利用できません。
これにより、工場、サービス、プロバイダーに関する理解が深まったことを願っています。
only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications
ように言っているので、聞こえませんか?
私にとって、啓示は、すべてが同じように動作することに気付いたときに発生しました。何かを一度実行し、取得した値を格納し、依存関係の注入を通じて参照されたときに、同じ格納された値を消去します。
私たちが持っているとしましょう:
app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);
3つの違いは次のとおりです。
a
の格納された値は、実行から取得されますfn
。b
の保存値はnew
ing から取得されますfn
。c
の格納された値は、最初にnew
ing によってインスタンスを取得し、fn
次に$get
インスタンスのメソッドを実行することから取得されます。これは、AngularJS内にキャッシュオブジェクトのようなものがあることを意味します。各インジェクションの値は、最初にインジェクションされたときに一度だけ割り当てられます。
cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()
これがthis
、サービスで使用しthis.$get
、プロバイダーでを定義する理由です。
factory
sで問題ありません。service
存在する唯一の理由は、CoffeeScript、TypeScript、ES6などの言語であるため、これらのクラス構文を使用できます。が必要なprovider
のは、を使用して、設定が異なる複数のアプリケーションでモジュールを使用する場合のみですapp.config()
。サービスが純粋なシングルトンであるか、または何かのインスタンスを作成できるかどうかは、実装に依存します。
サービスvsプロバイダーvs工場:
私はそれをシンプルに保つようにしています。基本的なJavaScriptの概念がすべてです。
まず最初に、AngularJSのサービスについて話しましょう!
サービスとは: AngularJSでは、サービスいくつかの便利なメソッドやプロパティを格納できるシングルトンJavaScriptオブジェクトにすぎません。このシングルトンオブジェクトはngApp(Angular app)ベースで作成され、現在のアプリ内のすべてのコントローラー間で共有されます。Angularjsはサービスオブジェクトをインスタンス化するときに、このサービスオブジェクトを一意のサービス名で登録します。したがって、サービスインスタンスが必要になるたびに、Angularはレジストリでこのサービス名を検索し、サービスオブジェクトへの参照を返します。そのため、サービスオブジェクトのメソッドを呼び出したり、プロパティにアクセスしたりできます。コントローラーのスコープオブジェクトにプロパティ、メソッドを配置できるかどうか疑問に思うかもしれません!では、なぜサービスオブジェクトが必要なのでしょうか。答えは次のとおりです。サービスは複数のコントローラースコープ間で共有されます。一部のプロパティ/メソッドをコントローラーのスコープオブジェクトに配置すると、現在のスコープでのみ使用できるようになります。
したがって、3つのコントローラースコープがある場合、コントローラーA、コントローラーB、コントローラーCとすると、すべてが同じサービスインスタンスを共有します。
<div ng-controller='controllerA'>
<!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
<!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
<!-- controllerC scope -->
</div>
サービスを作成するには?
AngularJSは、サービスを登録するためのさまざまなメソッドを提供します。ここでは、factory(..)、service(..)、provider(..)の3つのメソッドに集中します。
ファクトリ関数は以下のように定義できます。
factory('serviceName',function fnFactory(){ return serviceInstance;})
AngularJSは、serviceNameとJavaScript関数の2つのパラメーターを取る'factory(' serviceName '、fnFactory)'メソッドを提供します。Angularは、以下のような関数fnFactory()を呼び出すことでサービスインスタンスを作成します。
var serviceInstace = fnFactory();
渡された関数はオブジェクトを定義し、そのオブジェクトを返すことができます。AngularJSは、このオブジェクト参照を、最初の引数として渡される変数に格納するだけです。fnFactoryから返されるものはすべてserviceInstanceにバインドされます。オブジェクトを返す代わりに、関数や値などを返すこともできます。返すものは何でも、サービスインスタンスで利用できます。
例:
var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
var data={
'firstName':'Tom',
'lastName':' Cruise',
greet: function(){
console.log('hello!' + this.firstName + this.lastName);
}
};
//Now all the properties and methods of data object will be available in our service object
return data;
});
service('serviceName',function fnServiceConstructor(){})
それは別の方法です。サービスを登録できます。唯一の違いは、AngularJSがサービスオブジェクトをインスタンス化する方法です。今回、angularは 'new'キーワードを使用して、以下のようなコンストラクター関数を呼び出します。
var serviceInstance = new fnServiceConstructor();
コンストラクター関数では、サービスオブジェクトにプロパティ/メソッドを追加するために「this」キーワードを使用できます。例:
//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
this.firstName ='James';
this.lastName =' Bond';
this.greet = function(){
console.log('My Name is '+ this.firstName + this.lastName);
};
});
Provider()関数は、サービスを作成するもう1つの方法です。ユーザーに挨拶メッセージを表示するだけのサービスを作成してみましょう。しかし、ユーザーが独自の挨拶メッセージを設定できるような機能も提供したいと考えています。技術的には、構成可能なサービスを作成したいと考えています。どうすればこれを行うことができますか?アプリがカスタムグリーティングメッセージを渡し、Angularjsがサービスインスタンスを作成するファクトリー/コンストラクター関数で利用できるようにする方法が必要です。このような場合、provider()関数がその役割を果たします。provider()関数を使用して、構成可能なサービスを作成できます。
以下に示すプロバイダー構文を使用して、構成可能サービスを作成できます。
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});
/*step2:configure the service */
app.config(function configureService(serviceProvider){});
1.Providerオブジェクトは、プロバイダー関数で定義したコンストラクター関数を使用して作成されます。
var serviceProvider = new serviceProviderConstructor();
2. app.config()で渡した関数が実行されます。これは設定フェーズと呼ばれ、ここでサービスをカスタマイズする機会があります。
configureService(serviceProvider);
3.最後に、serviceProviderの$ getメソッドを呼び出すことにより、サービスインスタンスが作成されます。
serviceInstance = serviceProvider.$get()
var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
//this function works as constructor function for provider
this.firstName = 'Arnold ';
this.lastName = ' Schwarzenegger' ;
this.greetMessage = ' Welcome, This is default Greeting Message' ;
//adding some method which we can call in app.config() function
this.setGreetMsg = function(msg){
if(msg){
this.greetMessage = msg ;
}
};
//We can also add a method which can change firstName and lastName
this.$get = function(){
var firstName = this.firstName;
var lastName = this.lastName ;
var greetMessage = this.greetMessage;
var data={
greet: function(){
console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
}
};
return data ;
};
});
app.config(
function(providerPatternProvider){
providerPatternProvider.setGreetMsg(' How do you do ?');
}
);
概要:
ファクトリは、サービスインスタンスを返すファクトリ関数を使用します。 serviceInstance = fnFactory();
サービスはコンストラクター関数を使用し、Angularはサービスインスタンスを作成するために 'new'キーワードを使用してこのコンストラクター関数を呼び出します。 serviceInstance = new fnServiceConstructor();
プロバイダーはproviderConstructor関数を定義し、このproviderConstructor関数はファクトリー関数$ getを定義します。Angularは$ get()を呼び出してサービスオブジェクトを作成します。プロバイダーの構文には、インスタンス化される前にサービスオブジェクトを設定できるという利点があります。 serviceInstance = $ get();
ここで数人の人々が正しく指摘しているように、ファクトリー、プロバイダー、サービス、さらには価値と定数さえも同じもののバージョンです。より一般的なものprovider
をそれらすべてに分解することができます。そのようです:
この画像の記事は次のとおりです。
AngularJSに関数を与えると、AngularJSはファクトリがリクエストされたときに戻り値をキャッシュして注入します。
例:
app.factory('factory', function() {
var name = '';
// Return value **is** the object that will be injected
return {
name: name;
}
})
使用法:
app.controller('ctrl', function($scope, factory) {
$scope.name = factory.name;
});
AngularJSに関数を与えると、AngularJSはnewを呼び出してインスタンス化します。AngularJSが作成するインスタンスは、サービスが要求されたときにキャッシュされ、挿入されます。以来、新規にサービスをインスタンス化するために使用された、キーワードが、これは有効であり、インスタンスを指します。
例:
app.service('service', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.getName = function() {
return name;
}
});
使用法:
app.controller('ctrl', function($scope, service) {
$scope.name = service.getName();
});
AngularJSに関数を指定すると、AngularJSがその$get
関数を呼び出します。これは、$get
サービスが要求されたときにキャッシュおよび挿入される関数からの戻り値です。
プロバイダーを使用すると、AngularJSがメソッドを呼び出して注入可能オブジェクトを取得する前にプロバイダーを構成できます$get
。
例:
app.provider('provider', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.$get = function() {
return {
name: name
}
}
})
使用法(コントローラーの注入可能オブジェクトとして)
app.controller('ctrl', function($scope, provider) {
$scope.name = provider.name;
});
使用法($get
インジェクタブルを作成するために前にプロバイダーを構成することが呼び出されます)
app.config(function(providerProvider) {
providerProvider.setName('John');
});
プロバイダーで遊んでいるときに、何か面白いことに気づきました。
注射剤の可視性は、プロバイダーとサービスや工場では異なります。AngularJSを「定数」として宣言した場合(たとえば、myApp.constant('a', 'Robert');
)それをサービス、ファクトリー、プロバイダーに注入できます。
ただし、AngularJSの「値」(たとえば、myApp.value('b', {name: 'Jones'});
)を宣言した場合、サービスやファクトリに注入できますが、プロバイダー作成関数には注入できません。ただし、$get
プロバイダー用に定義した関数に挿入することはできます。これはAngularJSのドキュメントで言及されていますが、見落としがちです。これは、%provideページのvalueメソッドとconstantメソッドのセクションにあります。
<div ng-app="MyAppName">
<div ng-controller="MyCtrl">
<p>from Service: {{servGreet}}</p>
<p>from Provider: {{provGreet}}</p>
</div>
</div>
<script>
var myApp = angular.module('MyAppName', []);
myApp.constant('a', 'Robert');
myApp.value('b', {name: 'Jones'});
myApp.service('greetService', function(a,b) {
this.greeter = 'Hi there, ' + a + ' ' + b.name;
});
myApp.provider('greetProvider', function(a) {
this.firstName = a;
this.$get = function(b) {
this.lastName = b.name;
this.fullName = this.firstName + ' ' + this.lastName;
return this;
};
});
function MyCtrl($scope, greetService, greetProvider) {
$scope.servGreet = greetService.greeter;
$scope.provGreet = greetProvider.fullName;
}
</script>
これは初心者にとって非常に混乱する部分であり、簡単な言葉でそれを明確にしようとしました
AngularJSサービス:コントローラーのサービス参照とユーティリティ関数を共有するために使用されます。サービスは本質的にシングルトンであるため、1つのサービスに対して1つのインスタンスのみがブラウザーで作成され、同じ参照がページ全体で使用されます。
サービスでは、このオブジェクトのプロパティとして関数名を作成します。
AngularJS Factory:Factoryの目的もServiceと同じですが、この場合、新しいオブジェクトを作成し、このオブジェクトのプロパティとして関数を追加し、最後にこのオブジェクトを返します。
AngularJSプロバイダー:目的は同じですが、プロバイダーは$ get関数の出力を提供します。
サービス、ファクトリー、プロバイダーの定義と使用については、http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-providerで説明されています。
私にとって、違いを理解する最良かつ最も簡単な方法は次のとおりです。
var service, factory;
service = factory = function(injection) {}
AngularJSが特定のコンポーネントをインスタンス化する方法(簡略化):
// service
var angularService = new service(injection);
// factory
var angularFactory = factory(injection);
したがって、サービスの場合、AngularJSコンポーネントになるのは、サービス宣言関数によって表されるクラスのオブジェクトインスタンスです。ファクトリーの場合は、ファクトリー宣言関数から返された結果です。ファクトリはサービスと同じように動作します:
var factoryAsService = function(injection) {
return new function(injection) {
// Service content
}
}
最も単純な考え方は次のとおりです。
ファクトリの「クラス」の例は、コメントとプロバイダーの違いで提供されています。
new MyService()
何かができると期待していました:)
この問題についての私の説明:
基本的に、前述のすべてのタイプ(サービス、ファクトリー、プロバイダーなど)は、昔ながらのグローバル変数と同様に、グローバル変数(もちろん、アプリケーション全体に対してグローバルです)を作成して構成しているだけです。
グローバル変数は推奨されませんが、これらのグローバル変数の実際の使用法は、関連するコントローラーに変数を渡すことにより、依存性注入を提供することです。
「グローバル変数」の値の作成には、多くの複雑なレベルがあります。
app.config
app.config
関数は、ファクトリーと同じように動作します 上記では、その戻り値は「グローバル」変数を初期化するために使用されます。 以下の私の理解は非常に簡単です。
ファクトリー:ファクトリー 内にオブジェクトを作成し、それを返すだけです。
サービス:
このキーワードを使用して関数を定義する標準関数があります。
プロバイダー:
$get
定義したオブジェクトがあり、データを返すオブジェクトを取得するために使用できます。
Angular docsからの要約:
SOからの最良の回答:
https://stackoverflow.com/a/26924234/165673 (< - GOOD)
https://stackoverflow.com/a/27263882/165673
https://stackoverflow.com/a/16566144/165673
すべての良い答えはすでに。ServiceとFactoryについてもう少しポイントを追加したいと思います。サービス/工場の違いとともに。また、次のような質問をすることもできます。
サービスとファクトリーの違いから始めましょう:
どちらもシングルトンです。Angularがこれらを最初に依存関係として検出するたびに、サービス/ファクトリの単一のインスタンスが作成されます。インスタンスが作成されると、同じインスタンスが永久に使用されます。
動作のあるオブジェクトをモデル化するために使用できます。どちらもメソッド、内部状態変数などを持つことができます。ただし、そのコードの記述方法は異なります。
サービス:
サービスはコンストラクター関数であり、Angularはnewを呼び出してサービスをインスタンス化しますyourServiceName()
。これはいくつかのことを意味します。
this
。new yourServiceName(
)を呼び出すと、配置this
したすべてのプロパティを持つオブジェクトを受け取ります。サンプルの例:
angular.service('MyService', function() {
this.aServiceVariable = "Ved Prakash"
this.aServiceMethod = function() {
return //code
};
});
Angularがこの
MyService
サービスを依存するコントローラーに注入すると、そのコントローラーはMyService
MyService.aServiceMethod()などの関数を呼び出すことができるを取得します。
に注意してください this
:
構築されたサービスはオブジェクトなので、その中のメソッドは、呼び出されたときにこれを参照できます。
angular.service('ScoreKeeper', function($http) {
this.score = 0;
this.getScore = function() {
return this.score;
};
this.setScore = function(newScore) {
this.score = newScore;
};
this.addOne = function() {
this.score++;
};
});
ScoreKeeper.setScore
たとえば、サーバーからスコアを取得してスコアを初期化した場合、promiseチェーンを呼び出したくなるかもしれません。$http.get('/score').then(ScoreKeeper.setScore).
これの問題は、バインドされてScoreKeeper.setScore
呼び出され、エラーが発生することです。より良い方法はでしょう。これをサービスメソッドで使用するかどうかに関係なく、それらを呼び出す方法に注意してください。this
null
$http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper))
から値を返すService
:
JavaScriptコンストラクターの仕組みにより(i.e., an Object)
、constructor
関数から複雑な値を返す場合、呼び出し元はこのインスタンスではなくそのオブジェクトを取得します。
あなたは基本的には、下記から工場の例をコピー&ペースト置き換えることができ、この意味factory
でservice
、それがうまくいきます:
angular.service('MyService', function($http) {
var api = {};
api.aServiceMethod= function() {
return $http.get('/users');
};
return api;
});
したがって、Angularがnew MyService()を使用してサービスを構築すると、MyServiceインスタンスの代わりにそのAPIオブジェクトが取得されます。
これは複雑な値(オブジェクト、関数)の動作ですが、プリミティブ型の動作ではありません。
工場:
ファクトリーは、値を返すプレーンな古い関数です。戻り値は、ファクトリに依存するものに注入されるものです。Angularの典型的なファクトリパターンは、次のように、プロパティとして関数を持つオブジェクトを返すことです。
angular.factory('MyFactory', function($http) {
var api = {};
api.aFactoryMethod= function() {
return $http.get('/users');
};
return api;
});
ファクトリー依存関係に注入された値は、ファクトリーの戻り値であり、オブジェクトである必要はありません。関数かもしれません
上記の1および2の質問に対する回答:
ほとんどの場合、すべてにファクトリーを使用することに固執します。彼らの行動は理解しやすいです。値を返すかどうかを決める選択肢はありません。さらに、間違った操作を行ってもバグが発生することはありません。
ただし、依存関係として挿入することについて話しているときは、「サービス」と呼んでいます。
サービス/ファクトリーの動作は非常によく似ており、どちらかで問題ないと言う人もいます。それは幾分正しいですが、ジョンパパのスタイルガイドのアドバイスに従い、工場に固執する方が簡単だと思います。**
さらに説明すると、サービスでは作成できないのに、ファクトリでは関数/プリミティブを作成できます。Epokkに基づくこのjsFiddleを確認してください:http ://jsfiddle.net/skeller88/PxdSP/1351/。
ファクトリは、呼び出すことができる関数を返します。
myApp.factory('helloWorldFromFactory', function() {
return function() {
return "Hello, World!";
};
});
ファクトリは、呼び出すことができるメソッドでオブジェクトを返すこともできます。
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
サービスは、呼び出すことができるメソッドを持つオブジェクトを返します。
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
詳細については、違いについて書いた投稿を参照してください。http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/
良い答えはすでにありますが、私はこれを共有したいだけです。
まず第一に、プロバイダーは、を作成する方法/レシピですservice
$ injectorによって注入されることを想定し(シングルトンオブジェクト)(AngulaJSがIoCパターンを処理する方法)。
そして、Value、Factory、Service、Constant(4つの方法)- プロバイダーの方法/レセプトに対する構文上の砂糖。
Service vs Factory
カバーされている部分があります:https :
//www.youtube.com/watch?v=BLzNCkPn3ao
サービスとはnew
実際にキーワードに関するものであり、私たちが知っているように4つのことを行います。
prototype
オブジェクトにますcontext
しますthis
this
そしてファクトリーはすべてファクトリー・パターンに関するものです-そのサービスのようなオブジェクトを返す関数が含まれています。
そして、このシンプルな/短いビデオ:プロバイダーもカバーしています:https : //www.youtube.com/watch?v=HvTZbQ_hUZY(工場からプロバイダーにどのように移行するかがわかります)
プロバイダーレシピは、アプリが完全に起動/初期化される前に、主にアプリ構成で使用されます。
これらのすべての投稿を読んだ後、それは私にとってさらに混乱を引き起こしました..しかし、それでもすべての情報は価値があります..最後に、単純な比較で情報を提供する次の表を見つけました
そして、初心者のために理解してください:-これはユースケースを修正しないかもしれませんが、高レベルではこれはこれら3つのユースケースです。
angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})
基本的なシナリオでは、factory&Serviceは同じように動作します。
AngularjSのオブジェクトファクトリのコードテンプレートとして私が思いついたいくつかのブロイラープレートコードを次に示します。説明のために、例としてCar / CarFactoryを使用しました。コントローラーのシンプルな実装コードを作成します。
<script>
angular.module('app', [])
.factory('CarFactory', function() {
/**
* BroilerPlate Object Instance Factory Definition / Example
*/
this.Car = function() {
// initialize instance properties
angular.extend(this, {
color : null,
numberOfDoors : null,
hasFancyRadio : null,
hasLeatherSeats : null
});
// generic setter (with optional default value)
this.set = function(key, value, defaultValue, allowUndefined) {
// by default,
if (typeof allowUndefined === 'undefined') {
// we don't allow setter to accept "undefined" as a value
allowUndefined = false;
}
// if we do not allow undefined values, and..
if (!allowUndefined) {
// if an undefined value was passed in
if (value === undefined) {
// and a default value was specified
if (defaultValue !== undefined) {
// use the specified default value
value = defaultValue;
} else {
// otherwise use the class.prototype.defaults value
value = this.defaults[key];
} // end if/else
} // end if
} // end if
// update
this[key] = value;
// return reference to this object (fluent)
return this;
}; // end this.set()
}; // end this.Car class definition
// instance properties default values
this.Car.prototype.defaults = {
color: 'yellow',
numberOfDoors: 2,
hasLeatherSeats: null,
hasFancyRadio: false
};
// instance factory method / constructor
this.Car.prototype.instance = function(params) {
return new
this.constructor()
.set('color', params.color)
.set('numberOfDoors', params.numberOfDoors)
.set('hasFancyRadio', params.hasFancyRadio)
.set('hasLeatherSeats', params.hasLeatherSeats)
;
};
return new this.Car();
}) // end Factory Definition
.controller('testCtrl', function($scope, CarFactory) {
window.testCtrl = $scope;
// first car, is red, uses class default for:
// numberOfDoors, and hasLeatherSeats
$scope.car1 = CarFactory
.instance({
color: 'red'
})
;
// second car, is blue, has 3 doors,
// uses class default for hasLeatherSeats
$scope.car2 = CarFactory
.instance({
color: 'blue',
numberOfDoors: 3
})
;
// third car, has 4 doors, uses class default for
// color and hasLeatherSeats
$scope.car3 = CarFactory
.instance({
numberOfDoors: 4
})
;
// sets an undefined variable for 'hasFancyRadio',
// explicitly defines "true" as default when value is undefined
$scope.hasFancyRadio = undefined;
$scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);
// fourth car, purple, 4 doors,
// uses class default for hasLeatherSeats
$scope.car4 = CarFactory
.instance({
color: 'purple',
numberOfDoors: 4
});
// and then explicitly sets hasLeatherSeats to undefined
$scope.hasLeatherSeats = undefined;
$scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);
// in console, type window.testCtrl to see the resulting objects
});
</script>
簡単な例を示します。私は、緯度と経度を公開する「位置」オブジェクトを期待するいくつかのサードパーティライブラリを使用していますが、異なるオブジェクトプロパティを使用しています。ベンダーコードをハックしたくなかったので、渡していた「Position」オブジェクトを調整しました。
angular.module('app')
.factory('PositionFactory', function() {
/**
* BroilerPlate Object Instance Factory Definition / Example
*/
this.Position = function() {
// initialize instance properties
// (multiple properties to satisfy multiple external interface contracts)
angular.extend(this, {
lat : null,
lon : null,
latitude : null,
longitude : null,
coords: {
latitude: null,
longitude: null
}
});
this.setLatitude = function(latitude) {
this.latitude = latitude;
this.lat = latitude;
this.coords.latitude = latitude;
return this;
};
this.setLongitude = function(longitude) {
this.longitude = longitude;
this.lon = longitude;
this.coords.longitude = longitude;
return this;
};
}; // end class definition
// instance factory method / constructor
this.Position.prototype.instance = function(params) {
return new
this.constructor()
.setLatitude(params.latitude)
.setLongitude(params.longitude)
;
};
return new this.Position();
}) // end Factory Definition
.controller('testCtrl', function($scope, PositionFactory) {
$scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
$scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller
;
このページとドキュメントを参照として使用する(前回見たときから大幅に改善されているようです)をして、プロバイダーの5つのフレーバーのうち4つを使用する次の実際の(-ish)ワールドデモをまとめました。バリュー、コンスタント、ファクトリー、本格的なプロバイダー。
HTML:
<div ng-controller="mainCtrl as main">
<h1>{{main.title}}*</h1>
<h2>{{main.strapline}}</h2>
<p>Earn {{main.earn}} per click</p>
<p>You've earned {{main.earned}} by clicking!</p>
<button ng-click="main.handleClick()">Click me to earn</button>
<small>* Not actual money</small>
</div>
アプリ
var app = angular.module('angularProviders', []);
// A CONSTANT is not going to change
app.constant('range', 100);
// A VALUE could change, but probably / typically doesn't
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');
// A simple FACTORY allows us to compute a value @ runtime.
// Furthermore, it can have other dependencies injected into it such
// as our range constant.
app.factory('random', function randomFactory(range) {
// Get a random number within the range defined in our CONSTANT
return Math.random() * range;
});
// A PROVIDER, must return a custom type which implements the functionality
// provided by our service (see what I did there?).
// Here we define the constructor for the custom type the PROVIDER below will
// instantiate and return.
var Money = function(locale) {
// Depending on locale string set during config phase, we'll
// use different symbols and positioning for any values we
// need to display as currency
this.settings = {
uk: {
front: true,
currency: '£',
thousand: ',',
decimal: '.'
},
eu: {
front: false,
currency: '€',
thousand: '.',
decimal: ','
}
};
this.locale = locale;
};
// Return a monetary value with currency symbol and placement, and decimal
// and thousand delimiters according to the locale set in the config phase.
Money.prototype.convertValue = function(value) {
var settings = this.settings[this.locale],
decimalIndex, converted;
converted = this.addThousandSeparator(value.toFixed(2), settings.thousand);
decimalIndex = converted.length - 3;
converted = converted.substr(0, decimalIndex) +
settings.decimal +
converted.substr(decimalIndex + 1);
converted = settings.front ?
settings.currency + converted :
converted + settings.currency;
return converted;
};
// Add supplied thousand separator to supplied value
Money.prototype.addThousandSeparator = function(value, symbol) {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);
};
// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY
// are all effectively syntactic sugar built on top of the PROVIDER construct
// One of the advantages of the PROVIDER is that we can configure it before the
// application starts (see config below).
app.provider('money', function MoneyProvider() {
var locale;
// Function called by the config to set up the provider
this.setLocale = function(value) {
locale = value;
};
// All providers need to implement a $get method which returns
// an instance of the custom class which constitutes the service
this.$get = function moneyFactory() {
return new Money(locale);
};
});
// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider', function(moneyProvider) {
moneyProvider.setLocale('uk');
//moneyProvider.setLocale('eu');
}]);
// The ubiquitous controller
app.controller('mainCtrl', function($scope, title, strapline, random, money) {
// Plain old VALUE(s)
this.title = title;
this.strapline = strapline;
this.count = 0;
// Compute values using our money provider
this.earn = money.convertValue(random); // random is computed @ runtime
this.earned = money.convertValue(0);
this.handleClick = function() {
this.count ++;
this.earned = money.convertValue(random * this.count);
};
});
作業デモ。
この回答はトピック/質問に対処します
または
基本的に何が起こるか
あなたが作るときfactory()
、それはあなたがセットfunction
プロバイダのに第二引数で提供$get
し、(それを返すprovider(name, {$get:factoryFn })
)、あなたが得るすべてはあるprovider
が、以外にプロパティ/メソッドが存在しない$get
というのは、provider
(手段は、あなたがこれを設定することはできません)
工場のソースコード
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
};
これをservice()
返すときに、factory()にfunction
を注入してconstructor
(サービスで提供したコンストラクタのインスタンスを返す)、それを返します
サービスのソースコード
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
};
したがって、基本的にはどちらの場合でも、最終的にプロバイダー$ getを提供した関数に設定しますが、最初は構成ブロックのprovider()で提供できるので、$ get以外のものを追加できます。
私は優秀な答えをたくさん知っているが、私は使用しての私の経験を共有しなければならない
。1. service
デフォルトのほとんどの場合
2. factory
サービスその特定のインスタンスを作成するために使用されます
// factory.js ////////////////////////////
(function() {
'use strict';
angular
.module('myApp.services')
.factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];
function xFactoryImp($http) {
var fac = function (params) {
this._params = params; // used for query params
};
fac.prototype.nextPage = function () {
var url = "/_prc";
$http.get(url, {params: this._params}).success(function(data){ ...
}
return fac;
}
})();
// service.js //////////////////////////
(function() {
'use strict';
angular
.module('myApp.services')
.service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];
function xServiceImp($http) {
this._params = {'model': 'account','mode': 'list'};
this.nextPage = function () {
var url = "/_prc";
$http.get(url, {params: this._params}).success(function(data){ ...
}
}
})();
そして使用:
controller: ['xFactory', 'xService', function(xFactory, xService){
// books = new instance of xFactory for query 'book' model
var books = new xFactory({'model': 'book', 'mode': 'list'});
// accounts = new instance of xFactory for query 'accounts' model
var accounts = new xFactory({'model': 'account', 'mode': 'list'});
// accounts2 = accounts variable
var accounts2 = xService;
...
パーティーに少し遅れました。しかし、これは、ファクトリ、サービス、およびプロバイダーの方法論を使用してAngular JSカスタムサービスの開発について学びたい(または明確にしたい)方に役立つと思いました。
AngularJSカスタムサービスを開発するためのファクトリ、サービス、プロバイダーの方法論について明確に説明しているこのビデオに出くわしました。
https://www.youtube.com/watch?v=oUXku28ex-M
ソースコード:http : //www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service
ここに投稿されたコードは、読者のために、上記のソースから直接コピーされています。
「ファクトリー」ベースのカスタムサービスのコードは次のとおりです(httpサービスの呼び出しに加えて、同期バージョンと非同期バージョンの両方に対応しています)。
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
function($scope, calcFactory) {
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function() {
//$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
$scope.sum = r;
});
};
}
]);
app.factory('calcFactory', ['$http', '$log',
function($http, $log) {
$log.log("instantiating calcFactory..");
var oCalcService = {};
//oCalcService.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//oCalcService.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
oCalcService.getSum = function(a, b, cb) { //using http service
$http({
url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp) {
$log.log(resp.data);
cb(resp.data);
}, function(resp) {
$log.error("ERROR occurred");
});
};
return oCalcService;
}
]);
カスタムサービスの「サービス」方法論のコード(これは「ファクトリー」にかなり似ていますが、構文の観点とは異なります):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function(){
//$scope.sum = calcService.getSum($scope.a, $scope.b);
calcService.getSum($scope.a, $scope.b, function(r){
$scope.sum = r;
});
};
}]);
app.service('calcService', ['$http', '$log', function($http, $log){
$log.log("instantiating calcService..");
//this.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//this.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
this.getSum = function(a, b, cb){
$http({
url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp){
$log.log(resp.data);
cb(resp.data);
},function(resp){
$log.error("ERROR occurred");
});
};
}]);
カスタムサービスの「プロバイダー」方法論のコード(構成可能なサービスを開発する場合に必要です):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function(){
//$scope.sum = calcService.getSum($scope.a, $scope.b);
calcService.getSum($scope.a, $scope.b, function(r){
$scope.sum = r;
});
};
}]);
app.provider('calcService', function(){
var baseUrl = '';
this.config = function(url){
baseUrl = url;
};
this.$get = ['$log', '$http', function($log, $http){
$log.log("instantiating calcService...")
var oCalcService = {};
//oCalcService.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//oCalcService.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
oCalcService.getSum = function(a, b, cb){
$http({
url: baseUrl + '/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp){
$log.log(resp.data);
cb(resp.data);
},function(resp){
$log.error("ERROR occurred");
});
};
return oCalcService;
}];
});
app.config(['calcServiceProvider', function(calcServiceProvider){
calcServiceProvider.config("http://localhost:4467");
}]);
最後に、上記のサービスのいずれかと連携するUI:
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
<script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
<div ng-controller="emp">
<div>
Value of a is {{a}},
but you can change
<input type=text ng-model="a" /> <br>
Value of b is {{b}},
but you can change
<input type=text ng-model="b" /> <br>
</div>
Sum = {{sum}}<br>
<button ng-click="doSum()">Calculate</button>
</div>
</body>
</html>
明確にするために、AngularJSソースから、サービスがファクトリー関数を呼び出すだけで、プロバイダー関数を呼び出すことがわかります。
function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
簡単な方法でAngularJSでビジネスロジックを処理する3つの方法を議論してみましょう:(YaakovののコーセラAngularJSコースに触発さ)
SERVICE:
構文:
app.js
var app = angular.module('ServiceExample',[]);
var serviceExampleController =
app.controller('ServiceExampleController', ServiceExampleController);
var serviceExample = app.service('NameOfTheService', NameOfTheService);
ServiceExampleController.$inject = ['NameOfTheService'] //protects from minification of js files
function ServiceExampleController(NameOfTheService){
serviceExampleController = this;
serviceExampleController.data = NameOfTheService.getSomeData();
}
function NameOfTheService(){
nameOfTheService = this;
nameOfTheService.data = "Some Data";
nameOfTheService.getSomeData = function(){
return nameOfTheService.data;
}
}
index.html
<div ng-controller = "ServiceExampleController as serviceExample">
{{serviceExample.data}}
</div>
サービスの特徴:
工場
最初に構文を見てみましょう:
app.js:
var app = angular.module('FactoryExample',[]);
var factoryController = app.controller('FactoryController', FactoryController);
var factoryExampleOne = app.factory('NameOfTheFactoryOne', NameOfTheFactoryOne);
var factoryExampleTwo = app.factory('NameOfTheFactoryTwo', NameOfTheFactoryTwo);
//first implementation where it returns a function
function NameOfTheFactoryOne(){
var factory = function(){
return new SomeService();
}
return factory;
}
//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
var factory = {
getSomeService : function(){
return new SomeService();
}
};
return factory;
}
コントローラで上記の2つを使用します。
var factoryOne = NameOfTheFactoryOne() //since it returns a function
factoryOne.someMethod();
var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
factoryTwo.someMethod();
工場の特徴:
.service()
メソッドは、常に同じタイプのサービス(シングルトン)を生成するファクトリであり、その動作を簡単に構成する方法はありません。その.service()
方法は通常、設定をまったく必要としないもののショートカットとして使用されます。プロバイダー
最初にもう一度構文を見てみましょう。
angular.module('ProviderModule', [])
.controller('ProviderModuleController', ProviderModuleController)
.provider('ServiceProvider', ServiceProvider)
.config(Config); //optional
Config.$inject = ['ServiceProvider'];
function Config(ServiceProvider) {
ServiceProvider.defaults.maxItems = 10; //some default value
}
ProviderModuleController.$inject = ['ServiceProvider'];
function ProviderModuleController(ServiceProvider) {
//some methods
}
function ServiceProvider() {
var provider = this;
provider.defaults = {
maxItems: 10
};
provider.$get = function () {
var someList = new someListService(provider.defaults.maxItems);
return someList;
};
}
}
プロバイダーの機能:
.service
または.factory
メソッドでサービスを構成するときに、プロバイダーメソッドが実際に舞台裏で実行されることが言及されています。$get
直接プロバイダインスタンスに取り付けられている機能です。その関数はファクトリ関数です。つまり、メソッドに提供するために使用するものと同じ.factory
です。その機能では、独自のサービスを作成します。この$get
プロパティは関数であり、プロバイダーをプロバイダーにします。AngularJSは、プロバイダーが$ getプロパティを持ち、その値がAngularがファクトリー関数として扱う関数であることを期待しています。しかし、このプロバイダー全体のセットアップを非常に特別なものにしているのは、config
サービスプロバイダー内にオブジェクトを提供できることであり、通常は、アプリケーション全体を構成できるステップで後で上書きできるデフォルトが付属しています。基本的に、プロバイダー、ファクトリー、サービスはすべてサービスです。ファクトリは、必要なものが$ get()関数のみの場合のサービスの特殊なケースであり、少ないコードでそれを記述できます。
サービス、ファクトリー、プロバイダーの主な違いは、それらの複雑さです。サービスは最も単純な形式であり、ファクトリーはもう少し堅牢であり、プロバイダーは実行時に構成可能です。
次に、それぞれを使用するタイミングの概要を示します。
工場:提供する値は、他のデータに基づいて計算する必要があります。
サービス:メソッドを使用してオブジェクトを返しています。
プロバイダー:構成フェーズ中に、作成される前に作成されるオブジェクトを構成できるようにする必要があります。アプリが完全に初期化される前に、主にアプリ構成でプロバイダーを使用します。
1.Servicesは、必要に応じて作成されるシングルトンオブジェクトであり、アプリケーションのライフサイクルが終了する(ブラウザーが閉じられる)までクリーンアップされません。コントローラーは、不要になると破棄され、クリーンアップされます。
2.サービスを作成する最も簡単な方法は、factory()メソッドを使用することです。factory()メソッドを使用すると、サービス関数とサービスデータを含むオブジェクトを返すことにより、サービスを定義できます。サービス定義関数は、$ httpや$ qなどの注入可能なサービスを配置する場所です。例:
angular.module('myApp.services')
.factory('User', function($http) { // injectables go here
var backendUrl = "http://localhost:3000"; var service = {
// our factory definition
user: {},
setName: function(newName) {
service.user['name'] = newName;
},
setEmail: function(newEmail) { service.user['email'] = newEmail;
},
save: function() {
return $http.post(backendUrl + '/users', { user: service.user
}); }
};
return service; });
アプリでのfactory()の使用
実行時に必要な場所に注入するだけなので、アプリケーションでファクトリを使用するのは簡単です。
angular.module('myApp')
.controller('MainController', function($scope, User) {
$scope.saveUser = User.save;
});
構文糖は違いですです。プロバイダーのみが必要です。または言い換えれば、プロバイダーのみが実際の角度であり、他のすべてのものは(コードを削減するために)導出されます。Value()と呼ばれる単純なバージョンもあり、これは値だけを返し、計算や関数は返しません。値もプロバイダーから派生しています!
では、なぜこのような複雑な問題が発生するのか、なぜプロバイダーを使用して他のすべてを忘れないのでしょうか。それは私たちがコードを簡単に書き、より良いコミュニケーションをするのを助けることになっています。そして、舌のほほえみの返答は、それが複雑になるほど、フレームワークをよりよく売ることになります。
角度注入は、この結論に到達する最初のヒントになります。
"$ injectorは、サービスではなく、プロバイダーではなくプロバイダーによって定義されたオブジェクトインスタンスを取得するために使用されます。
「Angularサービスはサービスファクトリによって作成されます。これらのサービスファクトリは、サービスプロバイダーによって作成された関数です。サービスプロバイダーはコンストラクター関数です。インスタンス化されると、プロパティを含める必要があります。 $ getと呼ばれ、サービスファクトリ関数を保持します。」
したがって、マスタープロバイダーとインジェクター、およびすべてが適切に配置されます。そして、TypeServiceでは、IServiceProviderから継承することでプロバイダーに$ getを実装できるようになると興味深いものになります。