latest - AngularJS:サービス対プロバイダ




doc angularjs (20)

JSフィドルのデモ

factory / service / provider "Hello world"の例:

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

//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!";
    };
});

//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!";
        }
    };
});
    
//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!";
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});
        

function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
    
    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
    {{hellos}}
</div>
</body>

AngularJSのServiceProviderFactoryの違いは何ですか?


工場

AngularJSに関数を渡すと、AngularJSはファクトリが要求されたときに戻り値をキャッシュして注入します。

例:

app.factory('factory', function() {
    var name = '';
    // Return value **is** the object that will be injected
    return {
        name: name;
    }
})

使用法:

app.controller('ctrl', function($scope, factory) {
     $scope.name = factory.name;
});

サービス

あなたはAngularJSに関数を与え、AngularJSはそれをインスタンス化するためにnewを呼び出します。これは、サービスが要求されたときにキャッシュされ、注入されるAngularJSが作成するインスタンスです。newはサービスをインスタンス化するために使用されたので、キーワードthisは有効であり、インスタンスを参照します。

例:

app.service('service', function() {
     var name = '';
     this.setName = function(newName) {
         name = newName;
     }
     this.getName = function() {
         return name;
     }
});

使用法:

app.controller('ctrl', function($scope, service) {
   $scope.name = service.getName();
});

プロバイダ

AngularJSに関数を与え、AngularJSはその$get関数を呼び出します。これは、$getサービスが要求されたときにキャッシュされて注入される関数からの戻り値です。

プロバイダは、AngularJSが注入可能メソッドを呼び出すにプロバイダを設定することができます$get

例:

app.provider('provider', function() {
     var name = '';
     this.setName = function(newName) {
          name = newName;
     }
     this.$get = function() {
         return {
            name: name
         }
     }
})

使用法(コントローラー内の注射剤として)

app.controller('ctrl', function($scope, provider) {
    $scope.name = provider.name;
});

使用法($get注入可能なものを作成する前にプロバイダを設定する)

app.config(function(providerProvider) {
    providerProvider.setName('John');
});

AngularJSの工場、サービス、プロバイダーの理解

これらはすべて再利用可能なシングルトンオブジェクトを共有するために使用されます。 これは、アプリケーション/さまざまなコンポーネント/モジュール全体で再利用可能なコードを共有するのに役立ちます。

ドキュメントService/Factory

  • 緩やかにインスタンス化 - Angularは、アプリケーションコンポーネントが依存している場合にのみ、サービス/ファクトリをインスタンス化します。
  • シングルトン - サービスに依存する各コンポーネントは、サービスファクトリによって生成された単一インスタンスへの参照を取得します。

工場

ファクトリは、オブジェクトを作成する前にロジックを操作/追加し、新しく作成されたオブジェクトが返される関数です。

app.factory('MyFactory', function() {
    var serviceObj = {};
    //creating an object with methods/functions or variables
    serviceObj.myFunction = function() {
        //TO DO:
    };
    //return that object
    return serviceObj;
});

使用法

これは、クラスのような関数のコレクションにすぎません。 したがって、コントローラ/ファクトリ/ディレクティブ関数の中にそれを注入するときに、異なるコントローラでインスタンス化することができます。 これはアプリごとに1回だけインスタンス化されます。

サービス

サービスを見ている間は、配列のプロトタイプについて考えるだけです。 サービスは、 'new'キーワードを使用して新しいオブジェクトをインスタンス化する関数です。 thisキーワードを使用すると、サービスオブジェクトにプロパティと関数を追加できます。 ファクトリとは異なり、何も返しません(メソッド/プロパティを含むオブジェクトを返します)。

app.service('MyService', function() {
    //directly binding events to this context
    this.myServiceFunction = function() {
        //TO DO:
    };
});

使用法

アプリケーション全体で単一のオブジェクトを共有する必要がある場合に使用します。 例えば、認証されたユーザの詳細、共有可能なメソッド/データ、ユーティリティ関数など

プロバイダ

プロバイダは、構成可能なサービスオブジェクトを作成するために使用されます。 config機能からサービス設定を構成できます。 $get()関数を使用して値を返します。 $get関数は、実行フェーズで実行されます。

app.provider('configurableService', function() {
    var name = '';
    //this method can be be available at configuration time inside app.config.
    this.setName = function(newName) {
        name = newName;
    };
    this.$get = function() {
        var getName = function() {
             return name;
        };
        return {
            getName: getName //exposed object to where it gets injected.
        };
    };
});

使用法

サービスオブジェクトを利用可能にする前に、そのサービスオブジェクトのモジュール単位の構成を提供する必要がある場合。以下のようなあなたの環境に基づいて、あなたのAPIのURLを設定したいとしdevstageまたはprod

注意

コンフィグレーションフェーズではプロバイダのみが提供され、サービスとファクトリは提供されません。

これが工場、サービス、プロバイダーについてのあなたの理解を明確にしてくれることを願っています


Factory:ファクトリは、実際にファクトリの内部にオブジェクトを作成して返します。
service:関数を定義するのにthisキーワードを使用する標準関数を持つサービスです。
provider:プロバイダーには定義した$ getがあり、それを使用してデータを返すオブジェクトを取得できます。


サービス対プロバイダ対ファクトリ:

私はそれを簡単に保つために努力しています。基本的なJavaScriptの概念です。

まず、AngularJSのサービスについて話しましょう!

サービスとは: AngularJS、Serviceいくつかの便利なメソッドやプロパティを格納できるシングルトンJavaScriptオブジェクトです。このシングルトンオブジェクトは、ngApp(Angular app)ベースで作成され、現在のアプリ内のすべてのコントローラ間で共有されます。 Angularjsがサービスオブジェクトをインスタンス化するとき、Angularjsはこのサービスオブジェクトを一意のサービス名で登録します。したがって、サービスインスタンスが必要になるたびに、Angularはレジストリでこのサービス名を検索し、サービスオブジェクトへの参照を返します。そのようにして、メソッドを呼び出すことができ、サービスオブジェクトのプロパティなどにアクセスできます。コントローラのスコープオブジェクトにプロパティやメソッドを置くことができるかどうかという疑問があるかもしれません!では、なぜサービスオブジェクトが必要なのですか?答えは、複数のコントローラスコープ間でサービスを共有することです。コントローラのスコープオブジェクトにいくつかのプロパティ/メソッドを置くと、現在のスコープでのみ使用できます。しかし、サービスオブジェクトのメソッドやプロパティを定義すると、グローバルに利用できるようになり、そのサービスを注入することで任意のコントローラのスコープ内でアクセスできます。

したがって、コントローラスコープが3つある場合は、controllerA、controllerB、controllerCとし、すべて同じサービスインスタンスを共有します。

<div ng-controller='controllerA'>
    <!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
    <!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
    <!-- controllerC scope -->
</div>

サービスの作成方法

AngularJSは、サービスを登録するさまざまな方法を提供します。ここでは、3つのメソッドfactory(..)、service(..)、provider(..)に集中します。

コード参照にこのリンクを使用する

工場機能:

ファクトリ関数を以下のように定義することができます。

factory('serviceName',function fnFactory(){ return serviceInstance;})

AngularJSは、serviceNameとJavaScript関数の2つのパラメータを取る'factory(' serviceName '、fnFactory)メソッドを提供します。Angularは以下のような関数fnFactory()を呼び出してサービスインスタンスを作成します。

var serviceInstace = fnFactory();

渡された関数はオブジェクトを定義し、そのオブジェクトを返すことができます。AngularJSは、このオブジェクト参照を最初の引数として渡される変数に格納します。fnFactoryから返されたものはserviceInstanceにバインドされます。オブジェクトを返す代わりに、関数や値なども返すことができます。返すものがあれば、サービスインスタンスに利用できるようになります。

例:

var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
  var data={
    'firstName':'Tom',
    'lastName':' Cruise',
    greet: function(){
      console.log('hello!' + this.firstName + this.lastName);
    }
  };

  //Now all the properties and methods of data object will be available in our service object
  return data;
});

サービス機能:

service('serviceName',function fnServiceConstructor(){})

それは別の方法です、私たちはサービスを登録することができます。唯一の違いは、AngularJSがサービスオブジェクトのインスタンス化を試みる方法です。今回は、 'new'キーワードを使用し、以下のようなコンストラクタ関数を呼び出します。

var serviceInstance = new fnServiceConstructor();

コンストラクタ関数では、サービスオブジェクトにプロパティ/メソッドを追加するために 'this'キーワードを使用できます。 例:

//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
  this.firstName ='James';
  this.lastName =' Bond';
  this.greet = function(){
    console.log('My Name is '+ this.firstName + this.lastName);
  };
});

プロバイダ機能:

Provider()関数は、サービスを作成する別の方法です。ユーザーに挨拶メッセージを表示するだけのサービスを作成したいと考えましょう。しかし、ユーザーが独自の挨拶メッセージを設定できるような機能も提供したいと考えています。技術的には、構成可能なサービスを作成する必要があります。どうすればこのことができますか?アプリケーションが独自の挨拶メッセージを渡し、Angularjsがサービスインスタンスを作成するファクトリ/コンストラクタ関数で利用できるようにする方法が必要です。そのような場合、provider()関数はジョブを行います。provider()関数を使用して、構成可能なサービスを作成できます。

下記のプロバイダ構文を使用して構成可能なサービスを作成できます。

/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});

/*step2:configure the service */
app.config(function configureService(serviceProvider){});

プロバイダの構文は内部的にどのように機能しますか?

1.Providerオブジェクトは、プロバイダ関数で定義したコンストラクタ関数を使用して作成されます。

var serviceProvider = new serviceProviderConstructor();

2.app.config()で渡した関数が実行されます。これは設定フェーズと呼ばれ、ここで私たちのサービスをカスタマイズする機会があります。

configureService(serviceProvider);

3.サービスインスタンスは、serviceProviderの$ getメソッドを呼び出すことによって作成されます。

serviceInstance = serviceProvider.$get()

提供構文を使用してサービスを作成するためのサンプルコード:

var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
  //this function works as constructor function for provider
  this.firstName = 'Arnold ';
  this.lastName = ' Schwarzenegger' ;
  this.greetMessage = ' Welcome, This is default Greeting Message' ;
  //adding some method which we can call in app.config() function
  this.setGreetMsg = function(msg){
    if(msg){
      this.greetMessage =  msg ;
    }
  };

  //We can also add a method which can change firstName and lastName
  this.$get = function(){
    var firstName = this.firstName;
    var lastName = this.lastName ;
    var greetMessage = this.greetMessage;
    var data={
       greet: function(){
         console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
       }
    };
    return data ;
  };
});

app.config(
  function(providerPatternProvider){
    providerPatternProvider.setGreetMsg(' How do you do ?');
  }
);

作業デモ

概要:

ファクトリは、サービスインスタンスを返すファクトリ関数を使用します。serviceInstance = fnFactory();

サービスはコンストラクタ関数を使用し、Angularはサービスインスタンスを作成するために 'new'キーワードを使用してこのコンストラクタ関数を呼び出します。serviceInstance =新しいfnServiceConstructor();

ProviderはproviderConstructor関数を定義します。このproviderConstructor関数は$ getというファクトリ関数を定義します。角をつけて$ get()を呼び出して、サービスオブジェクトを作成します。プロバイダ構文には、インスタンス化する前にサービスオブジェクトを構成するという利点があります。serviceInstance = $ get();


AngularJSソースから物事を明確にするだけで、サービスが単にファクトリ関数を呼び出し、これが次にプロバイダ関数を呼び出すことがわかります。

function factory(name, factoryFn) { 
    return provider(name, { $get: factoryFn }); 
}

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
}

この回答はトピック/質問に対処します

ファクトリー、サービス、定数はどのようにプロバイダのレシピ上の文法的な砂糖ですか?

または

工場、サービス、プロバイダが内部的にどのように類似しているか

基本的に何が起こるか

あなたが作るときfactory()、それはあなたが設定functionプロバイダーのに第二引数で提供$getし、(それを返すにprovider(name, {$get:factoryFn }))、あなたが得るすべてはあるproviderが、以外にプロパティ/メソッドが存在しない$getというのは、provider(あなたがこれを設定することはできませんを意味します)

工場のソースコード

function factory(name, factoryFn, enforce) {
    return provider(name, {
      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
    });
};

a service()を返すと、factory()にa functionを渡します。これはconstructor(あなたのサービスで提供したコンストラクタのインスタンスを返して)返します

ソースコード

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
};

だから、基本的にどちらの場合でも、あなたは最終的にあなたが提供した関数にプロバイダ$を設定しますが、最初にprovider()で設定ブロックを提供できるように、$ get以上のものを与えることができます


これは初心者のための非常に混乱する部分です、私は簡単な言葉でそれを明確にしようとしました

AngularJS Service:コントローラ内のサービス参照とのユーティリティ機能の共有に使用されます。サービスは本質的にシングルトンなので、1つのサービスに対してブラウザでは1つのインスタンスしか作成されず、ページ全体で同じ参照が使用されます。

このサービスでは、このオブジェクトでプロパティとして関数名を作成します。

AngularJS Factory:Factoryの目的はServiceと同じですが、この場合は新しいオブジェクトを作成し、このオブジェクトのプロパティとして関数を追加し、最後にこのオブジェクトを返します。

AngularJS Provider:この目的は同じですが、プロバイダは$ get関数を出力します。

サービス、工場、プロバイダの定義と使用については、http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider説明していhttp://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider


すでに良い答えがありますが、私はこれを共有したいだけです。

まず最初に、プロバイダは、service$ injector(AngulaJSがIoCパターンについてどうやっているか)によって注入されると思われる(シングルトンオブジェクト)を作成するための方法/レシピです。

そしてValue、Factory、Service、Constant(4つの方法) - Provider Way / Recepie に対する構文上の砂糖。

次のService vs Factory部分がカバーされています:https://www.youtube.com/watch?v=BLzNCkPn3ao : https://www.youtube.com/watch?v=BLzNCkPn3ao

サービスはすべてnew、私たちが知っているように4つのことを行うキーワードです。

  1. 新しいオブジェクトを作成する
  2. prototypeオブジェクトにリンクする
  3. に接続contextするthis
  4. 返品 this

そしてFactoryはFactory Patternに関するもので、そのサービスのようなObjectを返す関数を含んでいます。

  1. 他のサービスを使用する能力(依存関係を持つ)
  2. サービスの初期化
  3. 遅延/遅延初期化

またこのシンプルなビデオは、プロバイダhttps://www.youtube.com/watch?v=HvTZbQ_hUZY : https://www.youtube.com/watch?v=HvTZbQ_hUZY(工場からプロバイダへの移行方法を見ることができます)

プロバイダのレシピは、アプリが完全に開始/初期化される前に、主にアプリの設定で使用されます。


すべてのサービスはシングルトンです。 アプリケーションごとに1回インスタンス化されます。 それらは、プリミティブ、オブジェクトリテラル、関数、またはカスタムタイプのインスタンスであっても、 どのようなタイプでもかまいません

valuefactoryserviceconstant 、およびproviderメソッドはすべてプロバイダです。 インジェクタは、サービスをインスタンス化する方法を教えます。

最も冗長で最も包括的なものはプロバイダレシピです。 残りの4つのレシピタイプ(Value、Factory、Service、Constant) は、プロバイダレシピの上に文法的な砂糖だけです

  • バリューレシピは最も単純なケースで、サービスを自分でインスタンス化しインスタンス化された値をインジェクタに提供します
  • ファクトリレシピは、インジェクタにサービスをインスタンス化する必要があるときに呼び出すファクトリ関数を提供します。 呼び出されると、 ファクトリ関数はサービスインスタンスを作成して返します。 関数の引数として、サービスの依存関係が挿入されます。 このレシピを使用すると、以下の能力が追加されます:
    • 他のサービスを使用する能力(依存関係を持つ)
    • サービスの初期化
    • 遅延/遅延初期化
  • サービスレシピはファクトリレシピとほとんど同じですが、ここではインジェクタはファクトリ関数ではなく新しい演算子でコンストラクタを呼び出します。
  • プロバイダーのレシピは通常過剰です。 ファクトリの作成を設定できるようにすることで、間接参照のレイヤを1つ追加します。

    プロバイダレシピは、アプリケーションを起動する前に行わなければならないアプリケーション全体の設定用にAPIを公開する場合にのみ使用する必要があります。 これは通常、アプリケーション間で動作がわずかに異なる必要がある再利用可能なサービスに対してのみ面白いです。

  • Constantレシピは、Valueフェーズで使用できるサービスを定義できる点を除いて、Valueレシピと同様です。 Valueレシピを使用して作成されたサービスよりも早く。 値とは異なり、 decoratorを使用してデコレーションすることはできません。
プロバイダのドキュメントを参照してください。


私の理解は非常に簡単です。

ファクトリ:ファクトリの内部にオブジェクトを作成して返すだけです。

サービス:

このキーワードを使用して関数を定義する標準関数があります。

プロバイダ:

$get定義したオブジェクトがあり、それを使用してデータを返すオブジェクトを取得できます。


私はプロバイダと遊んで面白い何かに気づいた。

注射剤の可視性は、サービスおよび工場の場合とは異なり、プロバイダーによって異なります。AngularJSの "定数"(たとえば、myApp.constant('a', 'Robert');)を宣言すると、サービス、工場、プロバイダに注入できます。

しかし、AngularJSの "値"(たとえば、。myApp.value('b', {name: 'Jones'});)を宣言すると、それをサービスや工場に注入できますが、プロバイダ作成関数に注入することはできません。ただし、$getプロバイダ用に定義した関数に挿入することはできます。これはAngularJSのドキュメントに記載されていますが、見逃しやすいです。値と定数メソッドのセクションの%提供ページで見つけることができます。

http://jsfiddle.net/R2Frv/1/

<div ng-app="MyAppName">
    <div ng-controller="MyCtrl">
        <p>from Service: {{servGreet}}</p>
        <p>from Provider: {{provGreet}}</p>
    </div>
</div>
<script>
    var myApp = angular.module('MyAppName', []);

    myApp.constant('a', 'Robert');
    myApp.value('b', {name: 'Jones'});

    myApp.service('greetService', function(a,b) {
        this.greeter = 'Hi there, ' + a + ' ' + b.name;
    });

    myApp.provider('greetProvider', function(a) {
        this.firstName = a;
        this.$get = function(b) {
            this.lastName = b.name;
            this.fullName = this.firstName + ' ' + this.lastName;
            return this;
        };
    });

    function MyCtrl($scope, greetService, greetProvider) {
        $scope.servGreet = greetService.greeter;
        $scope.provGreet = greetProvider.fullName;
    }
</script>

docs.angularjs.org/guide/providersからの要約:

  • オブジェクトの作成方法を定義するレシピタイプには、ValueFactoryServiceProviderConstant 5種類があります。
  • FactoryServiceは最も一般的に使用されるレシピです。それらの唯一の違いは、カスタムレシピのオブジェクトではサービスレシピがうまく機能し、ファクトリはJavaScriptのプリミティブと関数を生成できる点です。
  • プロバイダーレシピは、コアレシピの種類であり、他のすべてのものは、その上にだけ糖衣構文です。
  • プロバイダーは最も複雑なレシピタイプです。グローバルコンフィグレーションが必要な再利用可能なコードをビルドしている場合を除き、これは必要ありません。

SOからの最善の答え:

https://.com/a/26924234/165673(< - GOOD)https://.com/a/27263882/165673
https://.com/a/16566144/165673


AngularjSのオブジェクトファクトリのコードテンプレートとして私が考え出したいくつかのブロークプレートコードを示します。私は例としてCar / CarFactoryを使って説明しました。コントローラ内の簡単な実装コードを作成します。

     <script>
        angular.module('app', [])
            .factory('CarFactory', function() {

                /**
                 * BroilerPlate Object Instance Factory Definition / Example
                 */
                this.Car = function() {

                    // initialize instance properties
                    angular.extend(this, {
                        color           : null,
                        numberOfDoors   : null,
                        hasFancyRadio   : null,
                        hasLeatherSeats : null
                    });

                    // generic setter (with optional default value)
                    this.set = function(key, value, defaultValue, allowUndefined) {

                        // by default,
                        if (typeof allowUndefined === 'undefined') {
                            // we don't allow setter to accept "undefined" as a value
                            allowUndefined = false;
                        }
                        // if we do not allow undefined values, and..
                        if (!allowUndefined) {
                            // if an undefined value was passed in
                            if (value === undefined) {
                                // and a default value was specified
                                if (defaultValue !== undefined) {
                                    // use the specified default value
                                    value = defaultValue;
                                } else {
                                    // otherwise use the class.prototype.defaults value
                                    value = this.defaults[key];
                                } // end if/else
                            } // end if
                        } // end if

                        // update 
                        this[key] = value;

                        // return reference to this object (fluent)
                        return this;

                    }; // end this.set()

                }; // end this.Car class definition

                // instance properties default values
                this.Car.prototype.defaults = {
                    color: 'yellow',
                    numberOfDoors: 2,
                    hasLeatherSeats: null,
                    hasFancyRadio: false
                };

                // instance factory method / constructor
                this.Car.prototype.instance = function(params) {
                    return new 
                        this.constructor()
                                .set('color',           params.color)
                                .set('numberOfDoors',   params.numberOfDoors)
                                .set('hasFancyRadio',   params.hasFancyRadio)
                                .set('hasLeatherSeats', params.hasLeatherSeats)
                    ;
                };

                return new this.Car();

            }) // end Factory Definition
            .controller('testCtrl', function($scope, CarFactory) {

                window.testCtrl = $scope;

                // first car, is red, uses class default for:
                // numberOfDoors, and hasLeatherSeats
                $scope.car1     = CarFactory
                                    .instance({
                                        color: 'red'
                                    })
                                ;

                // second car, is blue, has 3 doors, 
                // uses class default for hasLeatherSeats
                $scope.car2     = CarFactory
                                    .instance({
                                        color: 'blue',
                                        numberOfDoors: 3
                                    })
                                ;
                // third car, has 4 doors, uses class default for 
                // color and hasLeatherSeats
                $scope.car3     = CarFactory
                                    .instance({
                                        numberOfDoors: 4
                                    })
                                ;
                // sets an undefined variable for 'hasFancyRadio',
                // explicitly defines "true" as default when value is undefined
                $scope.hasFancyRadio = undefined;
                $scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);

                // fourth car, purple, 4 doors,
                // uses class default for hasLeatherSeats
                $scope.car4     = CarFactory
                                    .instance({
                                        color: 'purple',
                                        numberOfDoors: 4
                                    });
                // and then explicitly sets hasLeatherSeats to undefined
                $scope.hasLeatherSeats = undefined;
                $scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);

                // in console, type window.testCtrl to see the resulting objects

            });
    </script>

ここにはより簡単な例があります。私は緯度と経度を公開する "Position"オブジェクトを期待するいくつかのサードパーティライブラリを使用していますが、異なるオブジェクトプロパティを使用しています。私はベンダーコードをハックしたくなかったので、私が渡していた "Position"オブジェクトを調整しました。

    angular.module('app')
.factory('PositionFactory', function() {

    /**
     * BroilerPlate Object Instance Factory Definition / Example
     */
    this.Position = function() {

        // initialize instance properties 
        // (multiple properties to satisfy multiple external interface contracts)
        angular.extend(this, {
            lat         : null,
            lon         : null,
            latitude    : null,
            longitude   : null,
            coords: {
                latitude: null,
                longitude: null
            }
        });

        this.setLatitude = function(latitude) {
            this.latitude           = latitude;
            this.lat                = latitude;
            this.coords.latitude    = latitude;
            return this;
        };
        this.setLongitude = function(longitude) {
            this.longitude          = longitude;
            this.lon                = longitude;
            this.coords.longitude   = longitude;
            return this;
        };

    }; // end class definition

    // instance factory method / constructor
    this.Position.prototype.instance = function(params) {
        return new 
            this.constructor()
                    .setLatitude(params.latitude)
                    .setLongitude(params.longitude)
        ;
    };

    return new this.Position();

}) // end Factory Definition

.controller('testCtrl', function($scope, PositionFactory) {
    $scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
    $scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller

;


このページとdocs.angularjs.org/guide/providers(私が最後に見たときから大幅に改善されているように見える)を参考にして、私はプロバイダの5つのフレーバーのうちの4つを使用する以下のリアル(-ish)世界デモをまとめました。バリュー、コンスタント、工場、フルブロー・プロバイダー。

HTML:

<div ng-controller="mainCtrl as main">
    <h1>{{main.title}}*</h1>
    <h2>{{main.strapline}}</h2>
    <p>Earn {{main.earn}} per click</p>
    <p>You've earned {{main.earned}} by clicking!</p>
    <button ng-click="main.handleClick()">Click me to earn</button>
    <small>* Not actual money</small>
</div>

アプリ

var app = angular.module('angularProviders', []);

// A CONSTANT is not going to change
app.constant('range', 100);

// A VALUE could change, but probably / typically doesn't
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');

// A simple FACTORY allows us to compute a value @ runtime.
// Furthermore, it can have other dependencies injected into it such
// as our range constant.
app.factory('random', function randomFactory(range) {
    // Get a random number within the range defined in our CONSTANT
    return Math.random() * range;
});

// A PROVIDER, must return a custom type which implements the functionality 
// provided by our service (see what I did there?).
// Here we define the constructor for the custom type the PROVIDER below will 
// instantiate and return.
var Money = function(locale) {

    // Depending on locale string set during config phase, we'll
    // use different symbols and positioning for any values we 
    // need to display as currency
    this.settings = {
        uk: {
            front: true,
            currency: '£',
            thousand: ',',
            decimal: '.'
        },
        eu: {
            front: false,
            currency: '€',
            thousand: '.',
            decimal: ','
        }
    };

    this.locale = locale;
};

// Return a monetary value with currency symbol and placement, and decimal 
// and thousand delimiters according to the locale set in the config phase.
Money.prototype.convertValue = function(value) {

    var settings = this.settings[this.locale],
        decimalIndex, converted;

    converted = this.addThousandSeparator(value.toFixed(2), settings.thousand);

    decimalIndex = converted.length - 3;

    converted = converted.substr(0, decimalIndex) +
        settings.decimal +
        converted.substr(decimalIndex + 1);    

    converted = settings.front ?
            settings.currency + converted : 
            converted + settings.currency; 

    return converted;   
};

// Add supplied thousand separator to supplied value
Money.prototype.addThousandSeparator = function(value, symbol) {
   return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);
};

// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY
// are all effectively syntactic sugar built on top of the PROVIDER construct
// One of the advantages of the PROVIDER is that we can configure it before the
// application starts (see config below).
app.provider('money', function MoneyProvider() {

    var locale;

    // Function called by the config to set up the provider
    this.setLocale = function(value) {
        locale = value;   
    };

    // All providers need to implement a $get method which returns
    // an instance of the custom class which constitutes the service
    this.$get = function moneyFactory() {
        return new Money(locale);
    };
});

// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider', function(moneyProvider) {
    moneyProvider.setLocale('uk');
    //moneyProvider.setLocale('eu'); 
}]);

// The ubiquitous controller
app.controller('mainCtrl', function($scope, title, strapline, random, money) {

    // Plain old VALUE(s)
    this.title = title;
    this.strapline = strapline;

    this.count = 0;

    // Compute values using our money provider    
    this.earn = money.convertValue(random); // random is computed @ runtime
    this.earned = money.convertValue(0);

    this.handleClick = function() { 
        this.count ++;
        this.earned = money.convertValue(random * this.count);
    };
});

ワーキングdemo


さらに明らかになるのは、ファクトリは関数/プリミティブを作成でき、サービスはできないということです。Epokkのhttp://jsfiddle.net/skeller88/PxdSP/1351/基づいてこのjsFiddleをチェックしてください。http://jsfiddle.net/skeller88/PxdSP/1351/

ファクトリは、呼び出すことができる関数を返します。

myApp.factory('helloWorldFromFactory', function() {
  return function() {
    return "Hello, World!";
  };
});

ファクトリは、呼び出すことのできるメソッドでオブジェクトを返すこともできます。

myApp.factory('helloWorldFromFactory', function() {
  return {
    sayHello: function() {
      return "Hello, World!";
    }
  };
});

このサービスは、呼び出すことのできるメソッドを持つオブジェクトを返します。

myApp.service('helloWorldFromService', function() {
  this.sayHello = function() {
     return "Hello, World!";
  };
});

詳細については、私がこの違いについて書いた記事を見てhttp://www.shanemkeller.com/tldr-services-vs-factories-in-angular/http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/ : http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/


パーティーには少し遅れた。しかし、これは、ファクトリー、サービス、プロバイダーの方法論を使ってAngular JS Custom Servicesを開発することを学びたい(または明快にしたい)人にとって、これがもっと役立つと思いました。

AngularJS Custom Servicesを開発するための工場、サービス、提供者の方法論について、このビデオではっきりと説明しました。

https://www.youtube.com/watch?v=oUXku28ex-M

ソースコード:http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service : http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service

ここに掲載されたコードは、上記のソースから直接コピーされ、読者に役立ちます。

「ファクトリ」ベースのカスタムサービスのコードは次のとおりです(これは、httpサービスを呼び出すとともに、同期バージョンと非同期バージョンの両方に対応します)。

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
  function($scope, calcFactory) {
    $scope.a = 10;
    $scope.b = 20;

    $scope.doSum = function() {
      //$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
      calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
        $scope.sum = r;
      });
    };

  }
]);

app.factory('calcFactory', ['$http', '$log',
  function($http, $log) {
    $log.log("instantiating calcFactory..");
    var oCalcService = {};

    //oCalcService.getSum = function(a,b){
    //	return parseInt(a) + parseInt(b);
    //};

    //oCalcService.getSum = function(a, b, cb){
    //	var s = parseInt(a) + parseInt(b);
    //	cb(s);
    //};

    oCalcService.getSum = function(a, b, cb) { //using http service

      $http({
        url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
        method: 'GET'
      }).then(function(resp) {
        $log.log(resp.data);
        cb(resp.data);
      }, function(resp) {
        $log.error("ERROR occurred");
      });
    };

    return oCalcService;
  }
]);

カスタムサービスのための "サービス"方法論のコード(これは 'factory'にかなり似ていますが、構文の観点とは異なります):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
	$scope.a = 10;
	$scope.b = 20;

	$scope.doSum = function(){
		//$scope.sum = calcService.getSum($scope.a, $scope.b);
		
		calcService.getSum($scope.a, $scope.b, function(r){
			$scope.sum = r;
		});		
	};

}]);

app.service('calcService', ['$http', '$log', function($http, $log){
	$log.log("instantiating calcService..");
	
	//this.getSum = function(a,b){
	//	return parseInt(a) + parseInt(b);
	//};

	//this.getSum = function(a, b, cb){
	//	var s = parseInt(a) + parseInt(b);
	//	cb(s);
	//};

	this.getSum = function(a, b, cb){
		$http({
			url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
			method: 'GET'
		}).then(function(resp){
			$log.log(resp.data);
			cb(resp.data);
		},function(resp){
			$log.error("ERROR occurred");
		});
	};

}]);

カスタムサービスの "プロバイダ"方法論のコード(構成可能なサービスを開発したい場合はこれが必要です):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
	$scope.a = 10;
	$scope.b = 20;

	$scope.doSum = function(){
		//$scope.sum = calcService.getSum($scope.a, $scope.b);
		
		calcService.getSum($scope.a, $scope.b, function(r){
			$scope.sum = r;
		});		
	};

}]);

app.provider('calcService', function(){

	var baseUrl = '';

	this.config = function(url){
		baseUrl = url;
	};

	this.$get = ['$log', '$http', function($log, $http){
		$log.log("instantiating calcService...")
		var oCalcService = {};

		//oCalcService.getSum = function(a,b){
		//	return parseInt(a) + parseInt(b);
		//};

		//oCalcService.getSum = function(a, b, cb){
		//	var s = parseInt(a) + parseInt(b);
		//	cb(s);	
		//};

		oCalcService.getSum = function(a, b, cb){

			$http({
				url: baseUrl + '/Sum?a=' + a + '&b=' + b,
				method: 'GET'
			}).then(function(resp){
				$log.log(resp.data);
				cb(resp.data);
			},function(resp){
				$log.error("ERROR occurred");
			});
		};		

		return oCalcService;
	}];

});

app.config(['calcServiceProvider', function(calcServiceProvider){
	calcServiceProvider.config("http://localhost:4467");
}]);

最後に、上記のサービスのいずれかで動作するUI:

<html>
<head>
	<title></title>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
	<script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
	<div ng-controller="emp">
		<div>
			Value of a is {{a}},
			but you can change
			<input type=text ng-model="a" /> <br>

			Value of b is {{b}},
			but you can change
			<input type=text ng-model="b" /> <br>

		</div>
		Sum = {{sum}}<br>
		<button ng-click="doSum()">Calculate</button>
	</div>
</body>
</html>


メモリの目的に基づいて、コントローラは必要な場合にのみインスタンス化され、必要でない場合は破棄されます。このため、ルートを切り替えたりページをリロードしたりするたびに、Angularは現在のコントローラをクリーンアップします。しかし、サービスはアプリケーションの存続期間中にデータを保持する手段を提供しますが、一貫した方法でさまざまなコントローラ間でデータを使用することもできます。

Angularは、独自のサービスを作成して登録する3つの方法を提供します。

1)工場

2)サービス

3)プロバイダ

ファクトリ:ファクトリは、オブジェクトを作成する前にロジックを追加できる単純な関数です。作成されたオブジェクトを返します。

それはクラスのような関数のコレクションです。したがって、コンストラクタ関数でそれを使用している場合、異なるコントローラでインスタンス化することができます。

サービス:サービスは、新しいキーワードを使用してオブジェクトを作成するコンストラクタ関数です。このキーワードを使用すると、サービスオブジェクトにプロパティと関数を追加できます。工場とは異なり、何も返されません。

これはシングルトンオブジェクトです。アプリケーション全体で単一のオブジェクトを共有する必要がある場合に使用します。たとえば、認証されたユーザーの詳細。

プロバイダ:プロバイダは、構成可能なサービスオブジェクトを作成するために使用されます。$ get()関数を使って値を返します。

サービスオブジェクトを使用可能にする前に、サービスオブジェクトのモジュール単位の構成を提供する必要がある場合。

次のコードを実行し、出力を確認します。

<!DOCTYPE html>
<html ng-app="app">
<head>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
    <meta charset=utf-8 />
    <title>JS Bin</title>
</head>
<body ng-controller="MyCtrl">
    {{serviceOutput}}
    <br/><br/>
    {{factoryOutput}}
    <br/><br/>
    {{providerOutput}}
    <script>
        var app = angular.module( 'app', [] );
        var MyFunc = function() {
            this.name = "default name";
            this.$get = function() {
                this.name = "new name"
                return "Hello from MyFunc.$get(). this.name = " + this.name;
            };
            return "Hello from MyFunc(). this.name = " + this.name;
        };
        // returns the actual function
        app.service( 'myService', MyFunc );
        // returns the function's return value
        app.factory( 'myFactory', MyFunc );
        // returns the output of the function's $get function
        app.provider( 'myProv', MyFunc );
        function MyCtrl( $scope, myService, myFactory, myProv ) {
            $scope.serviceOutput = "myService = " + myService;
            $scope.factoryOutput = "myFactory = " + myFactory;
            $scope.providerOutput = "myProvider = " + myProv;
        }
    </script>
</body>
</html>


私にとって、啓示は、彼らがすべて同じように働いていることに気がついたときに起こりました。何かを一度実行し、得た価値を保存し、依存性注入によって参照されたときに同じ保存値を咳をします。

私たちは持っていると言う:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

3つの違いは次のとおりです。

  1. aストアド・バリューは実行中fnです。
  2. b保存された値はnewing から来fnます。
  3. cストアされた値は、最初にインスタンスを取得し、そのインスタンスのメソッドを実行newすることによって得られます。fn$get

これはAngularJS内にキャッシュオブジェクトのようなものがあることを意味します。AngularJSの各インジェクションの値は最初にインジェクトされたときだけ割り当てられます。

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()

これが私たちthisがサービスで使用する理由でありthis.$get、プロバイダーで定義します。


私は優れた答えがたくさんあることを知っていますが、私は自分の経験を共有する必要があります
1. serviceデフォルトのほとんどの場合
2. factory特定のインスタンスを作成するために使用される

// factory.js ////////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];

function xFactoryImp($http) {
    var fac = function (params) {
        this._params = params; // used for query params
    };

    fac.prototype.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }
    return fac;
}
})();

// service.js //////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];

function xServiceImp($http) {  
    this._params = {'model': 'account','mode': 'list'};

    this.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }       
}
})();

および使用:

controller: ['xFactory', 'xService', function(xFactory, xService){

        // books = new instance of xFactory for query 'book' model
        var books = new xFactory({'model': 'book', 'mode': 'list'});

        // accounts = new instance of xFactory for query 'accounts' model
        var accounts = new xFactory({'model': 'account', 'mode': 'list'});

        // accounts2 = accounts variable
        var accounts2 = xService;
... 




angularjs-provider