LoginSignup
33
36

More than 5 years have passed since last update.

AngularJSで拡張ポイントを持つServiceを作成する.

Last updated at Posted at 2014-08-11

はじめに

このエントリは「"利用者側が設定を変更可能な"AngularのServiceの作成方法について」である.

以下のようなAngularJSのServiceがあったとしよう.

myModule.js
var module = angular.module('myModule', []);
module.factory('myService', function(){
  var message = 'Hello, world';
  return {
    hello: function(){
      return message;
    }
  };
});

↓のようにインジェクションすれば、 hello() が利用できる(何の面白みもない)Serviceだ

app.js
var app = angular.module('myApp', ['myModule']);

app.controller('MainCtrl', ['$scope', 'myService', function($scope, myService){
  $scope.message = myService.hello();
}]);

ここで、 hello() が返すメッセージをアプリケーションのモジュール毎に設定出来る用にしたいとする.

サービスプロバイダの利用.

モジュールの利用者側から設定可能なServiceとしたい時は、 $provide.provider を利用する.
なんぞそれ、という人もいるかもであるが、先ほどのコードで factory であったところを少しイジる程度だ.

myModule.js
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"] とすることで、モジュール側で作成したサービスプロバイダのコンストラクタにアクセスすることが出来る.

app.js
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.valuemodule.run の組み合わせを考慮した方がよい.
  • module.config には、サービスプロバイダと module.constant で定義した定数のみがインジェクション可能.
    • $injector$provide は例外的にインジェクション可能.
    • Service自体のインスタンス生成が実行されていないタイミングで、module.config が走る、という意味.
  • module.config の設定は、module._invokeQueue に登録されていき、この順序に従って実行される.
    • (やる価値があるかは別として)`angular.module('ng')._invokeQueueをイジると、AngularJS本体の組み込みモジュールのプロバイダ登録より早いタイミングで処理を挟み込むことも出来る.

参考

33
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
36