はじめに
このエントリは「"利用者側が設定を変更可能な"AngularのServiceの作成方法について」である.
以下のようなAngularJSのServiceがあったとしよう.
var module = angular.module('myModule', []);
module.factory('myService', function(){
var message = 'Hello, world';
return {
hello: function(){
return message;
}
};
});
↓のようにインジェクションすれば、 hello()
が利用できる(何の面白みもない)Serviceだ
var app = angular.module('myApp', ['myModule']);
app.controller('MainCtrl', ['$scope', 'myService', function($scope, myService){
$scope.message = myService.hello();
}]);
ここで、 hello()
が返すメッセージをアプリケーションのモジュール毎に設定出来る用にしたいとする.
サービスプロバイダの利用.
モジュールの利用者側から設定可能なServiceとしたい時は、 $provide.provider
を利用する.
なんぞそれ、という人もいるかもであるが、先ほどのコードで factory
であったところを少しイジる程度だ.
var module = angular.module('myModule', []);
module.provider('myService', function(){
var opt = {message: 'Hello, world'};
this.configure = function(options){
opt = angular.extend(opt, options);
};
this.$get = function(){
return {
hello: function(){
return opt.message;
}
};
};
});
ポイントは provider
を利用しているところと、 this...
の辺り.
provider
の使い方はおもに下記である:
-
provider
はサービスプロバイダのコンストラクタを引数としてセットする. - サービスプロバイダのコンストラクタは、
$get
メソッドを実装しなくてはならない(こいつが無い場合、Angularがエラーを吐く). -
$get
メソッドは関数であり、AngularのDI($inject
)経由でインジェクションされる際に呼び出される関数を実装する(factory(...)
でセットしていた関数と同様の位置づけ)
moduleの provider
はAngularのService登録において、最もプリミティブな関数である.
$provide.factory
や $provide.value
, $provide.service
は、全て $provide.provider
のラッパに過ぎない.
さて、利用側は↓のように、ポイントは、config["(サービス名)+Provider"]
とすることで、モジュール側で作成したサービスプロバイダのコンストラクタにアクセスすることが出来る.
var app = angular.module('myApp', ['myModule']);
app.config(['myServiceProvider', function(myServiceProvider){
myServiceProvider.configure({
message: 'My name is Quramy!'
});
}]);
app.controller('MainCtrl', ['$scope', 'myService', function($scope, myService){
$scope.message = myService.hello();
}]);
AngularJS本体でも、サービスプロバイダ経由で、利用者にServiceの設定を行う口を提供するパターンは多いため、下記等で目にしたこともあるのではないだろうか.
- Ajax($http) と
$httpProvider.interceptor
- ngRoute における
$routeProvider.when
- etc...
補足・豆知識
- サービスプロバイダにアクセス可能なのは、
module.config
のみである. - AnguarJSのアプリケーションが開始されてからは、サービスプロバイダにアクセスすることは出来ない.
- 逆に、アプリケーションを開始してからのServiceの挙動変更を許したいのであれば、
module.value
とmodule.run
の組み合わせを考慮した方がよい. -
module.config
には、サービスプロバイダとmodule.constant
で定義した定数のみがインジェクション可能. -
$injector
と$provide
は例外的にインジェクション可能. - Service自体のインスタンス生成が実行されていないタイミングで、
module.config
が走る、という意味. -
module.config
の設定は、module._invokeQueue
に登録されていき、この順序に従って実行される. - (やる価値があるかは別として)`angular.module('ng')._invokeQueueをイジると、AngularJS本体の組み込みモジュールのプロバイダ登録より早いタイミングで処理を挟み込むことも出来る.