LoginSignup
14
14

More than 5 years have passed since last update.

Angular# serviceとfactoryの違い

Last updated at Posted at 2016-04-19

Angular2.0の足音がだんだん聞こえてくるけど、1.x系でserviceとfactoryの違いにハマったのでメモ

factory service
何を定義? を返す関数を定義

値にはオブジェクトも含む
関数を定義

オブジェクトのコンストラクタを定義とも言える
何までOK? 値は数値、文字列、
オブジェクト、関数...なんでもOK
関数以外は不可
引数依存は? DIのこと 可能 可能
どういう時に使う? 文字列や数値を返したい
・他Angular moduleとインスタンスを共有したい
便利メソッドを集めたい・初期化処理が欲しい・class(typeScript/ES6)を使いたい

1.DIのこと $dependencyNameと引数名書くと、そのServiceとかをAngularが自動で入れてくれる依存性解決のやつ

コード(実例)を見る

以下はぶっちゃけ同じ

serviceAndFactory.js

// 独自オブジェクトのコンストラクタを定義(実際は無名関数が多い)
var myObjConstructor = function(){
  this.Hello = function(){ console.log("Hello!"); }
  this.Do = function(task){ console.log(task + "is done!"); }

  //prototypeで拡張した関数を呼ぶ
  this.ProtoMethod();
}

//prototypeで拡張
myObjConstructor.prototype.ProtoMethod = function(){
  console.log("Prototype Method");
  return 42; //人生、宇宙、すべての答えである数字
}

//使うとき(angular関係ない一般例)
var myObj = new myObjConstructor();



// ----------

var myModule = angular.module("myModule", []);

// サービスを定義。コンストラクタの関数を呼ぶ。自動で new myConstructor() される
myModule.service("myService", myObjConstructor);

// ファクトリーを定義。 new myConstructor() は自分でやる
myModule.factory("myFactory_1",
  function(){ 
     return new myObjConstructor();
  }
);

// ファクトリーは、他でnewしたインスタンスを渡してもOK
var myInstance = new myObjConstructor();
myModule.factory("myFactory_2", function(){ return myInstance; });

どれも、controllerとかでDIツール経由で入ってくるものは同じように使える。

使用例
myModule
.controller('myCtrl', function(myService, myFactory_1){
  if(myService.ProtoMethod() == myFactory_1.ProtoMethod()){
    console.log("Wow! 42!"); //必ずここを通るはず
  }
});

serviceとfactoryを間違えた場合

なんか動かないな???というとき…
TypeError: this.ProtoMethod is not a function とか
Error: [$injector:undef] Provider 'myService' must return a value from $get factory method.
とか言われていたら、おそらく factoryとserviceを間違えています。

ダメな例
myModule.factory("myService", myObjConstructor); // factoryに値を返さない関数を渡している 
とりあえず動く例
myModule.factory("myService", function(){ return new myObjConstructor() }); // 良いが冗長。
より良い例
myModule.service("myService", myObjConstructor); //"とりあえず動く例"でやっていた `return new...`部をAngularに任せている

service と factory 同じじゃね?  文字数少ないぶんserviceがよくね??

前述の例ではそうだけど、 オブジェクト(コンストラクタ関数)以外でも登録できる のがメリットのときもある…かも。

factoryでしか出来ないこと

myModule
.factory('httpPromise', function($http){
  // Promise を直接返すとか
  return $http().jsonp("http://jsonplaceholder.typicode.com/posts/1")
})
.factory('myValue', function(){
  // 非常に複雑な計算が必要だけど、1度計算したら使いまわしてOKな値とか…
  // 省略: 複雑な計算
  return 42;
})
.factory('myFunc', function(){
  // オブジェクトでなく関数を渡す
  return function(name){ console.log("hello, " + name); };
})
.controller('myCtrl2', function(httpPromise, myValue, myFunc){
  // Promiseを受け取って通信完了したら処理
  httpPromise.success(function(data){ console.log(data); }) 

  //複雑な計算結果だけ受け取る
  console.log(myValue);

  //関数を使う(valueレシピでもいいのでは)
  myFunc("Taro");
})
14
14
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
14
14