Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
AngularJS TIPS

AngularJS TIPS

パラメーター付きのサービスを定義するには?(providerメソッド)

2016年8月1日

value/service/factoryメソッドに比べてより原始的なproviderメソッドの利用場面を紹介し、使い分け指針をまとめる。またproviderメソッドを使ってサービスを定義する方法を解説する。

  • このエントリーをはてなブックマークに追加

 providerメソッドは、実は、サービス定義のための最も原始的なメソッドです。constantメソッド*1を除く、その他のサービスメソッド(valueservicefactoryメソッド)は、いずれも内部的にはproviderメソッドを呼び出しています。つまり、valueservicefactoryメソッドでできることは全てproviderメソッドでもできるということです。しかし、providerメソッドは万能な分、実装が冗長になりがちなので、一般的にはvalueservicefactoryメソッドを優先して利用します。

 providerメソッドを利用するのは、あくまでアプリ側で設定すべきパラメーター情報を持つようなサービスを定義する場合だけです。

  • *1 constantメソッドだけは、configメソッド配下で呼び出せるなど、特別な性質を持っていますので、providerメソッドには依存していません。

 それでは、具体的な例も見てみましょう。以下は、標準の$logサービスを拡張して、ログレベルによって出力すべきログをフィルターできるFilterLoggerサービスを定義してみます。指定できるログレベルは、以下の通りです。

ログレベル 出力するログ
0 ログを出力しない
1 errorだけを出力
2 error/warnを出力
3 error/warn/infoを出力
4 全て(error/warn/info/debug)を出力
指定できるログレベル

 具体的なコードは、以下の通りです。

JavaScript
angular.module('myAppService', [])
  .provider('FilterLog', function() {
    this.defaults = { level : 4 };         // 1

    this.$get = ['$log', function($log) {  // 23
      var level = this.defaults.level;

      return {
        error: function(message) {
          if (level > 0) {
            $log.error(message);
          }
        },
        warn: function(message) {
          if (level > 1) {
            $log.warn(message);
          }
        },
        info: function(message) {
          if (level > 2) {
            $log.info(message);
          }
        },
        debug: function(message) {
          if (level > 3) {
            $log.debug(message);
          }
        }
      }
    }];
  });
リスト1 providerメソッドでサービスを定義するためのコード(provider.js)

 providerメソッドの構文は、以下の通りです。

[構文]providerメソッド

provider(name, type)

  • name: サービスの名前
  • type: サービスを生成するための関数

 引数typeの記法は、他のサービスメソッドと比べると、やや複雑です。以下に詳細を読み解いていきます。

1公開したいパラメーターを定義する

 サービスとして後から設定可能なパラメーターはthis.パラメーター名 = 初期値の形式で定義できます。ここでは、defaultslevelパラメーターに初期値4を宣言しています。

2サービスの実体を$getメソッドで定義する

 providerサービスの実体は、$getメソッドで定義します。$getメソッドは、戻り値として、サービスのインスタンスを返さなければなりません。この例であれば、errorwarninfodebugメソッドを持ったオブジェクトリテラル(インスタンス)を返しています。

 errorwarninfodebugメソッドは、それぞれdefaultslevelパラメーターがそれぞれ決められた値より大きい場合に、$logサービスのerrorwarninfodebugメソッドを呼び出しています。

3既存のサービスを注入する

 サンプルでは、$getメソッドに対して$logサービスを注入していますが、実は、providerメソッドの引数typeそのものに対して注入することも可能です。

 ただし、引数typeの場合、注入できるサービスはconstantproviderサービスに限定される点に注意してください。

providerサービスを呼び出す

 以上を理解できたら、最後にproviderサービスを実際に呼び出してみましょう。

HTML
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8" />
<title>AngularJS TIPS</title>
</head>
<body ng-controller="MyController">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="scripts/provider.js"></script>
<script>
angular.module('myApp', ['myAppService'])
  .config(['FilterLogProvider', function(FilterLogProvider) {
    FilterLogProvider.defaults.level = 3;
  }])
  .controller('MyController', ['$scope', 'FilterLog',
    function($scope, FilterLog) {
    FilterLog.error('エラーが発生しました。');
    FilterLog.warn('警告が出ています。');
    FilterLog.info('情報があります。');
    FilterLog.debug('デバッグです。');
  }]);
</script>
</body>
</html>
リスト2 providerサービスを呼び出すためのコード(provider_app.html)
指定されたログレベル以上のログだけを出力
指定されたログレベル以上のログだけを出力

 providerサービスで定義されたパラメーターを指定するには、configメソッドに対して「サービス名+Provider」という名前でサービスを注入します。これによって、(ここでは)「FilterLogProvider.defaults.level」のようにパラメーターにアクセスできるようになります。

 あとは、これまでのサービスと同じく、コントローラーに対してサービスを注入することで、FilterLogサービスを利用できます(こちらは「Provider」という接尾辞は不要です)。

サービスメソッドの使い分け

 以上、サービスメソッドが出そろったところで、最後に、サービスメソッドの使い分けを整理しておきましょう。数あるサービスメソッドを整理する手掛かりにしてください。

1シンプルなグローバル変数/定数を定義したい場合

 valueconstantメソッドを利用します。サービスをconfigメソッドで呼び出す必要があるならばconstantメソッドを、それ以外のケースではvalueメソッドを使います。

2パラメーター付きのビジネスロジックを定義したい場合

 本稿で利用したproviderメソッドを利用します。

3パラメーターを持たないビジネスロジックを定義したい場合

 一般的にはserviceメソッドを利用しますが、すでにロジックがクラスとして用意されている、もしくはインスタンスを返すファクトリーメソッドが用意されている場合には、factoryメソッドの方が便利です。

処理対象:サービス カテゴリ:基本
処理対象:サービスの切り出し カテゴリ:基本
API:angular.Module カテゴリ:ng(コアモジュール) > type(型)

※以下では、本稿の前後を合わせて5回分(第65回~第69回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

AngularJS TIPS
65. アプリ内でよく利用するビジネスロジックを定義するには?(serviceメソッド)

より実践的なアプリ開発を行うために、アプリ固有のビジネスロジックをserviceメソッドによりサービスとして切り出し、それを呼び出す方法を説明する。

AngularJS TIPS
66. アプリ内でよく利用するビジネスロジックを定義するには?(factoryメソッド)

より実践的なアプリ開発を行うために、アプリ固有のビジネスロジックをfactoryメソッドによりサービスとして切り出し、それを呼び出す方法を説明する。

AngularJS TIPS
67. 【現在、表示中】≫ パラメーター付きのサービスを定義するには?(providerメソッド)

value/service/factoryメソッドに比べてより原始的なproviderメソッドの利用場面を紹介し、使い分け指針をまとめる。またproviderメソッドを使ってサービスを定義する方法を解説する。

AngularJS TIPS
68. AngularJSアプリの単体テストを実施するには?(準備編)

AngularJSで一般的に採用されているテスティングフレームワーク「Karma+Jasmin」による単体テスト環境を構築する手順を説明する。

AngularJS TIPS
69. AngularJSアプリの単体テストを実施するには?(実行編)

テスティングフレームワーク「Karma+Jasmin」を使って、AngularJSアプリの単体テストを記述して、それをテスト実行するまでの手順を説明する。

サイトからのお知らせ

Twitterでつぶやこう!