
AngularJSのサービス#AngularJS入門その5
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AngularJSのサービス
AngularJSにおけるサービスとは、アプリにおいて任意のタスクを実行する関数として使用されます。
例えば、AngularJSではajax通信用に$http組み込みサービスを持っています。
もちろん、サービスを自分で定義して使用することも可能です。
AngularJSでビジネスロジックはサービスとして実装されることが推奨されているため、
独自サービスを作成する機会は多いと思います。
その独自サービスをAngularJSで作成するには複数の方法があるので、それらの方法を確認してみましょう。
今回使用した動作環境は以下のとおりです。
なお、本記事で紹介しているコードは、以前作成したangular-seedを使って動作を確認しました。
- OS : MacOS X 10.9.2
- node.js : 0.10.24
- Git : 1.8.5.2
サービスを使う
AngularJSで独自定義のサービスを使用するには、Module#factoryを使用するか、
自分でモジュールconfig関数内部で$provideを使用してサービスを登録する必要があります。
また、すべてのサービスは前回解説したDIの仕組みを使用して登録することになります。
サービスを登録してみる
サービスを登録するには、そのサービスが全体の一部となるモジュールを持つようにします。
すると、モジュール用APIかconfig関数内の$provideサービスを使用してサービスを登録することができます。
//angular.Moduleを使用してサービス登録
var myModule = angular.module('myModule', []);
myModule.factory('myServiceId', function() {
  var myServiceInstance;
  /**
   *myServiceInstanceを作成.
   *ここでfactory関数を記述する
   */
  return myServiceInstance;
});
//$provideサービスを使用してサービス登録
angular.module('myModule', [], function($provide) {
  $provide.factory('myServiceId', function() {
    var myServiceInstance;
  /**
   *myServiceInstanceを作成.
   *ここでfactory関数を記述する
   */
    return myServiceInstance;
  });
});
サービスのインスタンスが登録されるわけではなく、サービスを作成するファクトリー関数が登録されます。
サービスの持つ機能
・依存性
サービスには依存性を指定することが可能です。ファクトリ関数の引数として指定すれば依存性を指定できます。
次の例は、AngularJS組み込みの$windowサービスに依存した関数を作成しています。
$windowサービスはfactoryによってファクトリー関数によってstackMessagesへ引数として引き渡されます。
//stackMessagesは受け取ったメッセージをスタックし、3つになったらアラート表示する
angular.module('myModule', [], function($provide) {
  $provide.factory('stackMessages', ['$window', function(win) {
    var msgArray = [];
    return function(msg) {
      msgArray.push(msg);
      if (msgs.length == 3) {
        win.alert(msgArray.join(""));
        msgArray = [];
      }
    };
  }]);
});
・サービスはシングルトン
AngularJSにおけるサービスは全てシングルトンになります。
インジェクター毎に与えられるサービスのインスタンスは、常に1つです。
・Angularサービスのインスタンス化
AngularJSの全てのサービスは、遅延してインスタンス化されます。そのため、サービスは必要になったときに
AngularJSによってインスタンス化されます。
コントローラでサービスを使う
サービスは、以前解説したAngularJSのコントローラへDIしてよく使用されます。
DIされるサービス名の文字列を含んだ配列の$injectプロパティを使用してサービス名を指定することが可能です。
 
サービス名は、AngularJSで登録されたサービスのIDと同じにしておく必要があります。
配列内のサービスの順番は、ファクトリー関数を呼び出す際に使用されます。
では公式ドキュメントサイトにある例を参考に、
コントローラとサービスを連携させたサンプルをつくってみます。
angular-seed/app/jsディレクトリにsample1.jsファイルを作成しましょう。
angular.
 module('MyServiceModule', []).
 factory('stackMessage', ['$window', function(win) {
    var msgs = [];
    return function(msg) {
      msgs.push(msg);
      if (msgs.length == 3) {
        win.alert(msgs.join("\n"));
        msgs = [];
      }
    };
  }]);
function myController(scope, notifyService) {
  scope.stackMessage = function(msg) {
    notifyService(msg);
  };
}
myController.$inject = ['$scope','stackMessage'];
MyServiceModuleでstackMessageサービス(関数)を作成し、myControllerにDIしています。
上記サービスとコントローラを使用するhtmlもappディレクトリにsample1.htmlという名前で作成します。
<!doctype html>
<html ng-app="MyServiceModule">
  <head>
    <script src="http://code.angularjs.org/1.2.3/angular.min.js"></script>
    <script src="js/sample1.js"></script>
  </head>
  <body>
    <div ng-controller="myController">
      <p>Let's try this simple notify service, injected into the controller...</p>
      <input ng-init="message='test'" ng-model="message" >
      <button ng-click="callNotify(message);">NOTIFY</button>
      <p>(you have to click 3 times to see an alert)</p>
    </div>
  </body>
</html>
ではサーバを起動し、ブラウザでアクセスしてみましょう。
% cd /path/your/angular-seed % node scripts/web-server.js Http Server running at http://localhost:8000/
http://localhost:8000/app/sample1.htmlにアクセスして動作を確認してみてください。
まとめ
今回は基本的なサービスの使い方について解説しました。
サービスの具体的な使い分け方についてはこちらもご確認ください。
参考サイトなど
- AngularJS公式: http://angularjs.org/
- angular-seed: https://github.com/angular/angular-seed
- 本blogでAngularJSタグのついた記事: https://dev.classmethod.jp/tag/angularjs/
- AngularJSのサービスについて : http://js.studio-kingdom.com/angularjs/guide/understanding_services










