連載
» 2016年04月07日 05時00分 UPDATE

MEANスタックで始めるWebアプリ開発入門(9):AngularJSの「サービス」で理解するDI(Dependency Injection:依存性注入)の基本 (1/2)

MEANスタックを用いたWebアプリの開発方法について紹介していく連載。今回は、ビジネスロジックを実行するAngularJSの「サービス」の概要と種類、使い方に加え、DI機能の概要と設定方法を紹介する。

[中村修太,クラスメソッド]

AngularJS 1.5リリース

 少し前になりますが、AngularJS 1.5がリリースされました(※2016年3月22日の原稿執筆時点での最新バージョンは1.5.2)このアップデートは、次期バージョン(AngularJS 2.0)へのアップグレードパス改善のためのリリースとなっています。主な変更点は次の通りです。

  • コンポーネントディレクティブの定義が可能に

 module.directiveの代わりにmodule.component関数を使用して、ディレクティブを定義できるようになりました。

  • $onInit()関数の呼び出しタイミングの変更

 $onInit()関数はバインディング設定後のコンポーネント初期化後に実行されるようになりました。

 その他の追加機能として、片方向のバインディング設定やECMAScript 6のサポートが強化されています。今後の連載では1.5xを使用していきます。

 さて、MEANスタックを用いたWebアプリの開発方法について紹介していく本連載「MEANスタックで始めるWebアプリ開発入門」。前回の「Web開発者が覚えておきたい、よく使うAngularJSのビルトインディレクティブ12選まとめ」では、AngularJSが持つビルトインディレクティブについて解説しました。今回はAngularJSの特徴である「Dependency Injection」(依存性注入)(以下、DI)と「サービス」について解説します。

 なお、本記事を見て実際にサンプルを動かしたい場合は、以前の連載記事(第1回第2回)を見て環境を作成しておきましょう。

ビジネスロジックを実行するAngularJSの「サービス」

 AngularJSにおける「サービス」とは、アプリにおいてビジネスロジックなどのタスクを実行する関数として使用されます。サービスを自分で定義して使うこともできますし、組み込みのサービス($http、$windowなど)を使うこともできます。

独自のサービスを作るには

 独自のサービスをAngularJSで作成するには幾つかの方法がありますが、ここではfactory関数を使ってサービス定義する方法を確認してみましょう。

 factory関数はサービスとして定義したい関数やオブジェクトを返します。

var myApp = angular.module('mySimpleApp', []);
 
myApp.factory('MyService', function () {
    return {
        say: function () {
            return "Hello!";
        }
    };
});

サービスはDIを使用しているものもある

 なお、AngularJSのサービスを実際に使用するためには、各コンポーネント(コントローラーやサービスなど)の依存関係を設定する必要があります。これは後述するDI機能を用いて設定することが可能です。

 また、作成したサービスはシングルトンとなります。

AngularJSの主なサービスの種類

 先ほどはfactory関数を使用してサービスの登録を行いましたが、AngularJSではサービスの種類に応じて関数を使い分けることができます。それぞれの用途を見てみましょう。

シンプルなオブジェクトを保持させる「value」

 この関数はシンプルなオブジェクトを保持させるために使用します。下記のようなオブジェクトやfunction(コンストラクタ)を指定可能です。

var myApp = angular.module('mySimpleApp', []);
 
//サービスの登録
myApp.value("user",
        {
            name: "taro",
            age: 30
        }
);

 なおvalueでは、後述するDIを使えないので注意してください。

共有したい関数やオブジェクトを返す「factory」

 共有したい関数やオブジェクトを返します。なお、返された値はシングルトンとなります。

var myApp = angular.module('mySimpleApp', []);
 
myApp.factory('myService2', function(){
    function say(){
        return "Hello!";
    }
 
    return {
        sayHello: function(){
            return say();
        }
    }
});

 factoryで登録されたサービスは後述するDIを使用することが可能です。

第2引数の関数をコンストラクタとして扱い、それをAngularJSのサービスとして登録する「service」

 第2引数の関数をコンストラクタとして扱い、それをAngularJSのサービスとして登録します。こちらは共有したいオブジェクトのfunction(コンストラクタ)を登録します。

var myApp = angular.module('mySimpleApp', []);
 
myApp.service('myService', function () {
    var service = {
        sayHello: function () {
            return "Hello!";
        }
    };
    return service;
});

 serviceでも後述するDIを使用可能です。

config関数にチェインさせてproviderの設定を変更できる「provider」

 providerの使い方はfactoryとだいたい同じですが、config関数にチェインさせてproviderの設定を変更できます。configは対象サービスのインスタンス生成時に実行され、providerで設定したフィールドを変更できます。

var myApp = angular.module('mySimpleApp', []);
 
myApp.provider('myService', function () {
 
    //外側から変更可能なフィールド
    this.name = 'taro';
 
    //この関数の戻り値がDIされる
    this.$get = function () {
 
        var name = this.name;
 
        return {
            sayHello: function () {
                console.log("Hello," + name);
            }
        }
    }
}).config(['myServiceProvider', function (myServiceProvider) {
    // 設定変更可能
    myServiceProvider.name = 'hanako';
 
}]);

 providerの中では$get関数を定義しており、この関数の実行した返り値がDIされます。ちなみに、既に説明したvalueやfactory、serviceは、内部でproviderを使用しています。

大まかな使い分けの方針

 ユーティリティー的な共通関数の集まりとして使用する場合はserviceを使い、コンストラクタを定義してオブジェクトとして扱いたい場合はfactoryを使用することが多いようです。サービスに対して任意の設定を行いたい場合にはproviderを使いましょう。

AngularJSのサービスを取得する「injector」

 登録したサービスは後述するDI機能を使用して使うことが多いですが、下記のようにinjectorを使用して明示的に取得することも可能です。

//injectしたいサービスを記述。ngも必要。
var $injector = angular.injector(['ng','mySimpleApp']);
 
//injectorからサービスを取得
var service = $injector.get('myService');
service.sayHello();
       1|2 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。