[angularjs] AngularJS : 서비스 대 공급자 대 팩토리

는 A의 차이점은 무엇입니까 Service, ProviderFactoryAngularJS와에가?



답변

AngularJS 메일 링리스트에서 서비스 대 팩토리 대 공급자 및 주입 사용법을 설명 하는 놀라운 스레드 를 얻었습니다 . 답변을 컴파일 :

서비스

구문 : module.service( 'serviceName', function );
결과 : serviceName을 주입 가능한 인수로 선언 하면 함수의 인스턴스가 제공됩니다. 다시 말해 new FunctionYouPassedToService() .

공장

구문 : module.factory( 'factoryName', function );
결과 : factoryName을 주입 가능한 인수로 선언하면 module.factory에 전달 된 함수 참조를 호출하여 리턴되는 값이 제공됩니다 . .

공급자

구문 : module.provider( 'providerName', function );
결과 : providerName을 주입 가능한 인수로 선언 하면이 제공됩니다 (new ProviderFunction()).$get() . 생성자 함수는 $ get 메소드가 호출되기 전에 인스턴스화 ProviderFunction됩니다. 함수 참조는 module.provider에 전달됩니다.

공급자는 모듈 구성 단계에서 구성 할 수 있다는 이점이 있습니다.

제공된 코드는 여기 를 참조 하십시오 .

Misko의 훌륭한 추가 설명은 다음과 같습니다.

provide.value('a', 123);

function Controller(a) {
  expect(a).toEqual(123);
}

이 경우 인젝터는 단순히 값을 그대로 반환합니다. 그러나 값을 계산하려면 어떻게해야합니까? 그런 다음 공장을 사용하십시오

provide.factory('b', function(a) {
  return a*2;
});

function Controller(b) {
  expect(b).toEqual(246);
}

그래서 factory가치 창출을 담당하는 기능도 입니다. 팩토리 기능은 다른 종속성을 요청할 수 있습니다.

그러나 더 많은 OO가되고 Greeter라는 클래스를 원한다면 어떻게해야합니까?

function Greeter(a) {
  this.greet = function() {
    return 'Hello ' + a;
  }
}

그런 다음 인스턴스화하려면 다음을 작성해야합니다.

provide.factory('greeter', function(a) {
  return new Greeter(a);
});

그런 다음 컨트롤러에서 ‘인사’를 요청할 수 있습니다.

function Controller(greeter) {
  expect(greeter instanceof Greeter).toBe(true);
  expect(greeter.greet()).toEqual('Hello 123');
}

그러나 그것은 너무 장황합니다. 이것을 쓰는 더 짧은 방법은provider.service('greeter', Greeter);

그러나 Greeter주입 전에 클래스 를 구성하려면 어떻게해야 합니까? 그럼 우리는 쓸 수 있습니다

provide.provider('greeter2', function() {
  var salutation = 'Hello';
  this.setSalutation = function(s) {
    salutation = s;
  }

  function Greeter(a) {
    this.greet = function() {
      return salutation + ' ' + a;
    }
  }

  this.$get = function(a) {
    return new Greeter(a);
  };
});

그런 다음이 작업을 수행 할 수 있습니다.

angular.module('abc', []).config(function(greeter2Provider) {
  greeter2Provider.setSalutation('Halo');
});

function Controller(greeter2) {
  expect(greeter2.greet()).toEqual('Halo 123');
}

보조 노트로서 service, factory그리고 value모든 공급자에서 파생됩니다.

provider.service = function(name, Class) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.instantiate(Class);
    };
  });
}

provider.factory = function(name, factory) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.invoke(factory);
    };
  });
}

provider.value = function(name, value) {
  provider.factory(name, function() {
    return value;
  });
};


답변

JS 피들 데모

“안녕하세요 세계”예와 factory/ service/ provider:

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>


답변

TL; DR

1) 당신이 사용하고있는 공장을 객체를 만든 다음 같은 개체를 반환, 그것에 속성을 추가 할 수 있습니다. 이 팩토리를 컨트롤러에 전달하면 이제 해당 컨트롤러에서 팩토리를 통해 객체의 해당 속성을 사용할 수 있습니다.

app.controller(‘myFactoryCtrl’, function($scope, myFactory){
  $scope.artist = myFactory.getArtist();
});

app.factory(‘myFactory’, function(){
  var _artist = Shakira’;
  var service = {};

  service.getArtist = function(){
    return _artist;
  }

  return service;
});

2) Service를 사용할 때 AngularJS는 ‘new’키워드를 사용하여 장면 뒤에서 인스턴스화합니다. 이 때문에 ‘this’에 속성을 추가하면 서비스는 ‘this’를 반환합니다. 서비스를 컨트롤러로 전달하면 이제 ‘this’에 대한 해당 속성을 서비스를 통해 해당 컨트롤러에서 사용할 수 있습니다.

app.controller(‘myServiceCtrl’, function($scope, myService){
  $scope.artist = myService.getArtist();
});

app.service(‘myService’, function(){
  var _artist = Nelly’;
  this.getArtist = function(){
    return _artist;
  }
});

3) 공급자 는 .config () 함수에 전달할 수있는 유일한 서비스입니다. 서비스 오브젝트를 사용하기 전에 모듈 전체 구성을 제공하려는 경우 제공자를 사용하십시오.

app.controller(‘myProvider’, function($scope, myProvider){
  $scope.artist = myProvider.getArtist();
  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

app.provider(‘myProvider’, function(){
 //Only the next two lines are available in the app.config()
 this._artist = ‘’;
 this.thingFromConfig = ‘’;
  this.$get = function(){
    var that = this;
    return {
      getArtist: function(){
        return that._artist;
      },
      thingOnConfig: that.thingFromConfig
    }
  }
});

app.config(function(myProviderProvider){
  myProviderProvider.thingFromConfig = This was set in config’;
});

비 TL; DR

1) 팩토리
팩토리는 서비스를 생성하고 구성하는 가장 보편적 인 방법입니다. TL; DR이 말한 것보다 훨씬 많지는 않습니다. 객체를 생성하고 속성을 추가 한 다음 동일한 객체를 반환하면됩니다. 그런 다음 팩토리를 컨트롤러로 전달하면 이제 해당 컨트롤러의 팩토리를 통해 객체의 해당 속성을 사용할 수 있습니다. 보다 광범위한 예는 다음과 같습니다.

app.factory(‘myFactory’, function(){
  var service = {};
  return service;
});

이제 ‘myFactory’를 컨트롤러에 전달하면 ‘service’에 첨부 한 모든 속성을 사용할 수 있습니다.

이제 콜백 함수에 ‘비공개’변수를 추가하겠습니다. 이것들은 컨트롤러에서 직접 액세스 할 수는 없지만 결국 ‘service’에서 getter / setter 메소드를 설정하여 필요할 때 이러한 ‘private’변수를 변경할 수 있습니다.

app.factory(‘myFactory’, function($http, $q){
  var service = {};
  var baseUrl = https://itunes.apple.com/search?term=’;
  var _artist = ‘’;
  var _finalUrl = ‘’;

  var makeUrl = function(){
   _artist = _artist.split(‘ ‘).join(‘+’);
    _finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
    return _finalUrl
  }

  return service;
});

여기서는 변수 / 함수를 ‘service’에 첨부하지 않습니다. 나중에 사용하거나 수정하기 위해 단순히 만들었습니다.

  • baseUrl은 iTunes API에 필요한 기본 URL입니다
  • _artist는 조회하고자하는 아티스트입니다.
  • _finalUrl은 iTunes를 호출 할 최종 완성 된 URL입니다.
  • makeUrl은 iTunes 친화적 인 URL을 생성하고 반환하는 기능입니다.

헬퍼 / 프라이빗 변수와 함수가 준비되었으므로 ‘service’객체에 속성을 추가해 봅시다. 우리가 ‘서비스’에 넣은 것은 ‘myFactory’를 전달하는 컨트롤러 내에서 직접 사용할 수 있습니다.

아티스트를 반환하거나 설정하는 setArtist 및 getArtist 메소드를 작성하려고합니다. 또한 생성 된 URL을 사용하여 iTunes API를 호출하는 메소드를 작성하려고합니다. 이 방법은 일단 데이터가 iTunes API에서 돌아 오면 이행 할 것을 약속합니다. AngularJS에서 약속을 사용한 경험이 많지 않은 경우 약속을 자세히 살펴 보는 것이 좋습니다.

아래 setArtist 는 아티스트를 허용하며 아티스트를 설정할 수 있습니다. getArtist 는 아티스트를 반환합니다. callItunes 는 $ http 요청에 사용할 URL을 만들기 위해 makeUrl ()을 먼저 호출합니다. 그런 다음 promise 객체를 설정하고 최종 URL로 $ http 요청을 한 다음 $ http는 promise를 반환하므로 요청 후 .success 또는 .error를 호출 할 수 있습니다. 그런 다음 iTunes 데이터로 약속을 해결하거나 ‘오류가 발생했습니다’라는 메시지와 함께 거부합니다.

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  service.setArtist = function(artist){
    _artist = artist;
  }

  service.getArtist = function(){
    return _artist;
  }

  service.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

  return service;
});

이제 우리 공장은 완성되었습니다. 이제 모든 컨트롤러에 ‘myFactory’를 주입 할 수 있으며 서비스 객체 (setArtist, getArtist 및 callItunes)에 첨부 한 메소드를 호출 할 수 있습니다.

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.data = {};
  $scope.updateArtist = function(){
    myFactory.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myFactory.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

위의 컨트롤러에서 우리는 ‘myFactory’서비스에 주입하고 있습니다. 그런 다음 ‘myFactory’의 데이터를 사용하여 $ scope 객체의 속성을 설정합니다. 위의 유일한 까다로운 코드는 이전에 약속을 다루지 않은 경우입니다. callItunes가 약속을 반환하므로 .then () 메서드를 사용하고 iTunes 데이터로 약속이 이행 된 후에 만 ​​$ scope.data.artistData를 설정할 수 있습니다. 컨트롤러가 매우 얇다는 것을 알 수 있습니다 (이것은 좋은 코딩 연습입니다). 모든 논리 및 영구 데이터는 컨트롤러가 아닌 서비스에 있습니다.

2) 서비스
아마도 서비스 생성을 처리 할 때 알아야 할 가장 큰 것은 ‘새로운’키워드로 인스턴스화된다는 것입니다. JavaScript 전문가에게는 이것이 코드의 특성에 대한 큰 힌트를 제공해야합니다. JavaScript에 대한 배경 지식이 제한적인 사용자 또는 ‘new’키워드의 실제 기능에 익숙하지 않은 사용자를 위해 서비스의 본질을 이해하는 데 도움이되는 JavaScript 기본 사항을 검토하겠습니다.

‘new’키워드로 함수를 호출 할 때 발생하는 변경 사항을 실제로 보려면 함수를 작성하고 ‘new’키워드로 호출 한 다음 ‘new’키워드를 볼 때 인터프리터가 수행하는 작업을 보여 드리겠습니다. 최종 결과는 동일합니다.

먼저 생성자를 만들어 봅시다.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}

일반적인 JavaScript 생성자 함수입니다. 이제 ‘new’키워드를 사용하여 Person 함수를 호출 할 때마다 ‘this’는 새로 작성된 오브젝트에 바인드됩니다.

이제 Person의 프로토 타입에 메소드를 추가하여 Person ‘클래스’의 모든 인스턴스에서 사용할 수 있습니다.

Person.prototype.sayName = function(){
  alert(‘My name is  + this.name);
}

이제 프로토 타입에 sayName 함수를 추가 했으므로 Person의 모든 인스턴스는 해당 인스턴스 이름을 알리기 위해 sayName 함수를 호출 할 수 있습니다.

이제 Person 생성자 함수와 프로토 타입에 sayName 함수가 있으므로 Person 인스턴스를 만든 다음 sayName 함수를 호출 해 보겠습니다.

var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

따라서 Person 생성자를 생성하고 프로토 타입에 함수를 추가하고 Person 인스턴스를 생성 한 다음 프로토 타입에서 함수를 호출하는 코드는 다음과 같습니다.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  alert(‘My name is  + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

이제 JavaScript에서 ‘new’키워드를 사용할 때 실제로 어떤 일이 발생하는지 살펴 보겠습니다. 첫 번째로 주목해야 할 것은 예제에서 ‘new’를 사용한 후에는 마치 ‘tyler’에서 객체 인 것처럼 메소드 (sayName)를 호출 할 수 있다는 것입니다. 그 이유 때문입니다. 먼저, Person 생성자가 코드에서 볼 수 있는지 여부에 관계없이 Person 생성자가 객체를 반환한다는 것을 알고 있습니다. 둘째, sayName 함수는 Person 인스턴스가 아닌 프로토 타입에 있으므로 Person 함수가 반환하는 객체는 실패한 조회에서 프로토 타입에 위임되어야합니다. 더 간단한 용어로, tyler.sayName ()을 호출하면 인터프리터는“OK, 방금 만든 ‘tyler’객체를보고 sayName 함수를 찾은 다음 호출합니다. 잠깐만 요, 여기 보이지 않습니다-내가 볼 수있는 것은 이름과 나이, 프로토 타입을 확인하겠습니다. 예, 프로토 타입에있는 것 같습니다.”라고 말합니다.

아래는 JavaScript에서 ‘new’키워드가 실제로하는 일에 대해 어떻게 생각할 수 있는지에 대한 코드입니다. 기본적으로 위 단락의 코드 예입니다. 나는 ‘인터프리터 뷰’또는 인터프리터가 코드 내부의 코드를 보는 방식을 넣었습니다.

var Person = function(name, age){
  //The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
  //var obj = Object.create(Person.prototype);

  //The line directly below this sets ‘this’ to the newly created object
  //this = obj;

  this.name = name;
  this.age = age;

  //return this;
}

이제 ‘new’키워드가 JavaScript에서 실제로 수행하는 작업에 대한 지식이 있으면 AngularJS에서 서비스를 작성하는 것이 이해하기 쉬워야합니다.

서비스를 만들 때 이해해야 할 가장 큰 것은 서비스가 ‘new’키워드로 인스턴스화된다는 것입니다. 위의 예제와 그 지식을 결합하여 이제 속성과 메소드를 ‘this’에 직접 첨부하여 서비스 자체에서 반환한다는 것을 인식해야합니다. 이것을 실제로 살펴 봅시다.

우리가 팩토리 예제로 원래했던 것과는 달리, 우리는 객체를 생성 할 필요가 없습니다. 이전에 여러 번 언급했듯이 인터프리터가 해당 객체를 생성하고 위임 할 수 있도록 ‘new’키워드를 사용했기 때문입니다. 그것은 프로토 타입이고, 우리가 작업을하지 않아도 우리를 위해 그것을 돌려줍니다.

먼저, ‘비공개’및 도우미 기능을 만들어 봅시다. 우리가 공장과 똑같은 일을했기 때문에 이것은 매우 친숙하게 보일 것입니다. 팩토리 예제에서 각 라인이 무엇을하는지 설명하지 않겠습니다. 혼란 스러우면 팩토리 예제를 다시 읽으십시오.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
});

이제 컨트롤러에서 사용할 수있는 모든 메소드를 ‘this’에 첨부하겠습니다.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.setArtist = function(artist){
    _artist = artist;
  }

  this.getArtist = function(){
    return _artist;
  }

  this.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

});

이제 팩토리 에서처럼 setArtist, getArtist 및 callItunes는 myService를 전달하는 컨트롤러에서 사용할 수 있습니다. 다음은 myService 컨트롤러입니다 (공장 컨트롤러와 거의 동일).

app.controller('myServiceCtrl', function($scope, myService){
  $scope.data = {};
  $scope.updateArtist = function(){
    myService.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myService.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

앞에서 언급했듯이 ‘새로운’기능을 실제로 이해하면 서비스는 AngularJS의 공장과 거의 동일합니다.

3) 공급자

제공자에 대해 기억해야 할 가장 큰 것은 제공자가 애플리케이션의 app.config 부분으로 전달할 수있는 유일한 서비스라는 것입니다. 애플리케이션의 다른 곳에서 사용하기 전에 서비스 오브젝트의 일부를 변경해야하는 경우 이는 매우 중요합니다. 서비스 / 공장과 매우 ​​유사하지만 몇 가지 차이점이 있습니다.

먼저 우리는 서비스 및 공장과 비슷한 방식으로 공급자를 설정했습니다. 아래 변수는 ‘비공개’및 도우미 기능입니다.

app.provider('myProvider', function(){
   var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below.
  this.thingFromConfig = ‘’;

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
}

* 위 코드의 일부가 혼란 스러우면 팩토리 섹션에서 자세한 내용을 설명합니다.

제공자는 3 개의 섹션이 있다고 생각할 수 있습니다. 첫 번째 섹션은 나중에 수정 / 설정 될 ‘비공개’변수 / 함수입니다 (위 그림 참조). 두 번째 섹션은 app.config 함수에서 사용할 수있는 변수 / 함수이므로 다른 곳에서 사용 가능하기 전에 변경할 수 있습니다 (위에 표시됨). 이러한 변수는 ‘this’키워드에 첨부해야합니다. 이 예에서는 app.config에서 ‘thingFromConfig’만 변경할 수 있습니다. 세 번째 섹션 (아래 참조)은 ‘myProvider’서비스를 특정 컨트롤러로 전달할 때 컨트롤러에서 사용할 수있는 모든 변수 / 기능입니다.

Provider로 서비스를 생성 할 때 컨트롤러에서 사용할 수있는 유일한 속성 / 방법은 $ get () 함수에서 반환되는 속성 / 방법입니다. 아래 코드는 $ get을 ‘this’에 넣습니다. 이제 $ get 함수는 컨트롤러에서 사용할 수있는 모든 메소드 / 속성을 반환합니다. 다음은 코드 예입니다.

this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }

이제 전체 제공자 코드는 다음과 같습니다

app.provider('myProvider', function(){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below
  this.thingFromConfig = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }
});

이제 팩토리 및 서비스 에서처럼 setArtist, getArtist 및 callItunes는 myProvider를 전달하는 컨트롤러에서 사용할 수 있습니다. 다음은 myProvider 컨트롤러입니다 (공장 / 서비스 컨트롤러와 거의 동일).

app.controller('myProviderCtrl', function($scope, myProvider){
  $scope.data = {};
  $scope.updateArtist = function(){
    myProvider.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myProvider.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }

  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

앞에서 언급했듯이 Provider를 사용하여 서비스를 만드는 요점은 최종 객체가 나머지 응용 프로그램으로 전달되기 전에 app.config 함수를 통해 일부 변수를 변경할 수 있다는 것입니다. 그 예를 보자.

app.config(function(myProviderProvider){
  //Providers are the only service you can pass into app.config
  myProviderProvider.thingFromConfig = 'This sentence was set in app.config. Providers are the only service that can be passed into config. Check out the code to see how it works';
});

이제 제공자에서 ‘thingFromConfig’가 빈 문자열로 어떻게 표시되는지 확인할 수 있지만 DOM에 표시되면 ‘이 문장이 설정되었습니다…’가됩니다.


답변

모든 서비스는 싱글 톤입니다 . 앱마다 한 번씩 인스턴스화됩니다. 프리미티브, 객체 리터럴, 함수 또는 사용자 정의 유형의 인스턴스이든 관계없이 모든 유형 이 될 수 있습니다 .

value, factory, service, constant, 및 provider방법은 모든 공급자입니다. 그들은 인젝터에게 서비스를 인스턴스화하는 방법을 가르칩니다.

가장 장황하지만 가장 포괄적 인 것은 제공자 레시피입니다. 나머지 4 개 조리법 유형 – 값, 공장, 서비스 및 상수는 – 공급자 조리법의 상단에 단지 문법 설탕 있습니다 .

  • 값 레시피는 당신이 서비스를 직접 인스턴스화하고 제공하는 간단한 경우이다 인스턴스화 값 인젝터에 있습니다.
  • 공장 조리법은 이 서비스의 인스턴스를 필요로 할 때 호출하는 인젝터를 공장 기능을 제공합니다. 호출되면 팩토리 함수 는 서비스 인스턴스를 작성하고 리턴합니다. 서비스의 종속성은 함수의 인수로 삽입됩니다. 이 레시피를 사용하면 다음과 같은 능력이 추가됩니다.
    • 다른 서비스를 사용할 수있는 기능 (종속성이 있음)
    • 서비스 초기화
    • 지연 / 지연 초기화
  • 서비스 조리법은 거의 공장 조리법과 동일하지만, 여기에 인젝터는 호출 생성자 new 연산자 대신 공장 기능을.
  • 제공자 조리법은 일반적으로 과잉 . 팩토리 작성을 구성 할 수 있도록하여 간접 계층을 하나 더 추가합니다.

    응용 프로그램을 시작하기 전에 작성해야하는 응용 프로그램 전체 구성에 대한 API를 노출하려는 경우에만 제공자 레시피를 사용해야합니다. 이것은 일반적으로 응용 프로그램마다 동작이 약간 다를 수있는 재사용 가능한 서비스에만 유용합니다.

  • 상수 조리법은 그냥 당신이에서 사용할 수있는 서비스를 정의 할 수 있습니다 제외하고는 값 조리법처럼 구성 단계. Value 레시피를 사용하여 생성 된 서비스보다 빨리. 값과 달리을 사용하여 꾸밀 수는 없습니다 decorator.

공급자 설명서를
참조하십시오 .


답변

AngularJS 팩토리, 서비스 및 제공자 이해

이들 모두는 재사용 가능한 싱글 톤 객체를 공유하는 데 사용됩니다. 앱 / 다양한 구성 요소 / 모듈에서 재사용 가능한 코드를 공유하는 데 도움이됩니다.

Docs 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;
});

용법

클래스와 같은 함수 모음 일 수 있습니다. 따라서 컨트롤러 / 공장 / 지시 기능 내부에 주입 할 때 다른 컨트롤러에서 인스턴스화 할 수 있습니다. 앱당 한 번만 인스턴스화됩니다.

서비스

서비스를 보면서 간단히 어레이 프로토 타입에 대해 생각하십시오. 서비스는 ‘new’키워드를 사용하여 새 객체를 인스턴스화하는 기능입니다. this키워드 를 사용하여 서비스 개체에 속성과 기능을 추가 할 수 있습니다 . 팩토리와 달리 아무것도 반환하지 않습니다 (메소드 / 속성을 포함하는 객체를 반환합니다).

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

용법

응용 프로그램 전체에서 단일 객체를 공유해야 할 때 사용하십시오. 예를 들어, 인증 된 사용자 정보, 공유 가능한 방법 / 데이터, 유틸리티 기능 등

공급자

공급자는 구성 가능한 서비스 개체를 만드는 데 사용됩니다. 구성 기능에서 서비스 설정을 구성 할 수 있습니다. $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을 설정하려는 가정 dev, stage또는prod

노트

angular의 구성 단계에서는 공급자 만 사용할 수 있지만 서비스 및 팩토리는 제공되지 않습니다.

이것이 공장, 서비스 및 공급자에 대한 이해를 명확하게 해주길 바랍니다 .


답변

저에게 계시는 그들이 모두 같은 방식으로 작동한다는 것을 깨달았을 때 나타났습니다. 무언가를 한 번 실행하고 얻은 값을 저장 한 다음 의존성 주입을 통해 참조 할 때 동일한 저장된 값 을 기침합니다 .

우리가 가지고 있다고합시다.

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

세 가지의 차이점은 다음과 같습니다.

  1. a저장된 값은 실행에서 비롯됩니다 fn.
  2. b저장된 가치는 newing 에서 나옵니다 fn.
  3. c‘저장 s의 값은 첫번째로 인스턴스를 얻기에서 오는 new보내고 fn, 다음 실행중인 $get인스턴스의 방법을.

이것은 AngularJS 내부에 캐시 객체와 같은 것을 의미합니다. 각 주입 값은 처음 주입되었을 때 한 번만 할당되며 어디서 :

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

이것이 우리 this가 서비스에서 사용 this.$get하고 공급자를 정의하는 이유 입니다.


답변

서비스 대 공급자 대 공장 :

간단하게 유지하려고합니다. 기본 JavaScript 개념에 관한 것입니다.

우선 AngularJS의 서비스 에 대해 이야기합시다 !

서비스 란? :
AngularJS에서 서비스유용한 메소드 또는 속성을 저장할 수있는 싱글 톤 JavaScript 객체 일뿐입니다. 이 싱글 톤 객체는 ngApp (Angular app) 단위로 생성되며 현재 앱 내의 모든 컨트롤러간에 공유됩니다. Angularjs는 서비스 객체를 인스턴스화 할 때이 서비스 객체를 고유 한 서비스 이름으로 등록합니다. 따라서 서비스 인스턴스가 필요할 때마다 Angular는이 서비스 이름에 대한 레지스트리를 검색하고 서비스 객체에 대한 참조를 반환합니다. 서비스 객체에서 메소드를 호출하고 속성에 액세스 할 수 있도록합니다. 컨트롤러의 스코프 객체에 속성, 메소드를 넣을 수 있는지에 대한 의문이 생길 수 있습니다! 왜 서비스 객체가 필요합니까? 답은 여러 컨트롤러 범위에서 서비스를 공유한다는 것입니다. 컨트롤러의 범위 객체에 일부 속성 / 메소드를 넣으면 현재 범위에서만 사용할 수 있습니다.

따라서 컨트롤러 범위가 세 개인 경우 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는 서비스를 등록하는 다른 방법을 제공합니다. 여기서 우리는 세 가지 방법 factory (..), service (..), provider (..)에 집중할 것입니다.

코드 참조를 위해이 링크를 사용하십시오

공장 기능 :

아래와 같이 팩토리 함수를 정의 할 수 있습니다.

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

AngularJS는 serviceName과 JavaScript 함수라는 두 개의 매개 변수를 사용하는 ‘factory (‘serviceName ‘, fnFactory)’ 메서드를 제공합니다. Angular 는 아래와 같이 fnFactory () 함수를 호출하여 서비스 인스턴스를 만듭니다 .

var serviceInstace = fnFactory();

전달 된 함수는 객체를 정의하고 해당 객체를 반환 할 수 있습니다. AngularJS는 단순히이 객체 참조를 첫 번째 인수로 전달되는 변수에 저장합니다. fnFactory에서 반환 된 것은 serviceInstance에 바인딩됩니다. object를 반환하는 대신 함수, 값 등을 반환 할 수도 있습니다. 반환 할 내용은 서비스 인스턴스에서 사용할 수 있습니다.

예:

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가 서비스 객체를 인스턴스화하는 방식입니다. 이번에는 angular는 ‘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. 제공자 객체는 제공자 함수에서 정의한 생성자 함수를 사용하여 생성됩니다.

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 ();

공급자 는 providerConstructor 함수를 정의하고이 providerConstructor 함수는 팩토리 함수 $ get을 정의합니다 . Angular는 $ get ()을 호출하여 서비스 객체를 만듭니다. 공급자 구문에는 서비스 개체를 인스턴스화하기 전에 구성 할 수있는 이점이 있습니다.
serviceInstance = $ get ();