2014-04-12 8 views
4

나는 angularjs 서비스와 공장에 관한 여러 글을 읽었다. 나는 서비스가 싱글 톤이고 팩토리가 객체의 인스턴스를 반환한다는 것을 알고있다. 그러나 나는 아직도 그것들을 사용하는 방법을 정말로 모른다. 내 응용 프로그램은 간단한 소셜 네트워크입니다. 앱을 사용하는 사람이 로그인해야만 다른 회원을보고 메시지를 보낼 수 있습니다.여전히 angularjs 서비스와 공장에 대해 혼동을 느낀다.

내 이상적인 디자인은 다음과 같습니다

  1. 내 서비스의 임의의 구성원을 대표하는 회원 개체를 만듭니다. 'list'또는 'get'연산이 데이터를 반환 할 때마다이 멤버에 래핑되어 유틸리티 메서드를 호출 할 수 있습니다. 나는 이걸 위해 공장을 쓸거야.
  2. 사용자가 앱에 로그인하면 해당 사용자를 나타내는 멤버를 만들고 (나중에 인증 된 요청을 위해 사용자 ID와 인증 토큰 포함) 이것은 다른 범위에서 사용할 수 있어야하므로 $ rootScope에 첨부하거나 인증 된 사용자에 맞게 조정 된 Member의 인스턴스를 반환하는 MemberService가 될 수 있습니다.

내가 만든 다음

angular.module('myapp.models', []) 
.factory('Member', ['$log', 'DataService', '$http', 'Restangular', 
    function($log, DataService, $http, Restangular) { 
     return { 
      user_id: null, 
      first_name: null, 
      last_name: null, 

      authenticate: function(username, password, loginSuccessHandler, loginErrorHandler) { 
       $log.debug("inside Member.authenticate"); 

       var authSuccessHandler = function(data, status, headers, config) { 
        $http.defaults.headers.common.Authorization = 'Basic ' + btoa(data._id + ':' + data.token); 
        var token = btoa(data._id + ':' + data.token); 
        user_id = data._id;  // attach this to the rootScope? Needs to be 
               // globally accessible (or even this whole object) 
        Restangular.setDefaultHeaders({'Authorization': 'Basic ' + token}); 
        $log.debug("Auth successful, token stored " + token); 
        loginSuccessHandler(); 
       }; 

       DataService.authenticate(username, password, authSuccessHandler, authErrorHandler); 
      }, 
     ... 

어떻게이를 인스턴스화하고 다른 범위에서 사용할 수 있도록 (예를 들어, 다른 범위에서 그래서는 사용자의 ID 로그인 알고있는 것) 할 수 있습니까?

또한 구성원 목록을 구문 분석 할 때이 개체의 인스턴스를 만들 수 있습니까? 예 : 객체가있는 경우 {first_name: "John", last_name: "Smith"} 어떻게 이러한 속성을 가진이 팩토리에서 Member 객체를 얻을 수 있습니까?

+0

어쨌든 그것을 사용하려고하는 이유보다는 뭔가의 원리를 이해하기 너무 어려운 경우 내가 항상 말을? –

답변

8

factoryserviceprovider 이상의 추상화입니다.

function provider(name, provider_) { 
    if (isFunction(provider_) || isArray(provider_)) { 
     provider_ = providerInjector.instantiate(provider_); 
    } 
    if (!provider_.$get) { 
     throw Error('Provider ' + name + ' must define $get factory method.'); 
    } 
    return providerCache[name + providerSuffix] = provider_; 
} 

첫 번째 부분이 때 각 응용 프로그램로드까지 새로운 (싱글) 객체를 인스턴스화 :

새로운 공급자를 인스턴스화 각도에 의해 사용되는 방법이다. $get 메서드는 새 개체의 생성자로 사용됩니다. 이것은 provider의 인스턴스화 (의 각 문서에서)처럼 보이게하는 방법입니다 :

myApp.provider('unicornLauncher', function UnicornLauncherProvider() { 
    var useTinfoilShielding = false; 

    this.useTinfoilShielding = function(value) { 
    useTinfoilShielding = !!value; 
    }; 

    this.$get = ["apiToken", function unicornLauncherFactory(apiToken) { 

    // let's assume that the UnicornLauncher constructor was also changed to 
    // accept and use the useTinfoilShielding argument 
    return new UnicornLauncher(apiToken, useTinfoilShielding); 
    }]; 
}); 

다음은 공급자를 구성하는 방법입니다. module.config() 블록에서 나중에 컨트롤러/지시문/서비스에 공급자를 삽입 할 때와 달리 $get 메서드의 반환 값보다는 싱글 톤을 얻습니다.

myApp.config(["unicornLauncherProvider", function(unicornLauncherProvider) { 
    unicornLauncherProvider.useTinfoilShielding(true); 
}]); 

그런 다음 주입 및 unicornLauncher를 호출 할 때마다 $get 방법에 무엇이 호출되는 것이며,이 경우에 공급 된 구성으로 새로운 UnicornLauncher, useTinfoilShielding = true을 얻을 것이다.

보시다시피 제공 업체에는 두 부분이 있습니다. 첫째, 각도가 올라갈 때 인스턴스화되고 구성된 싱글 톤이며 providerCache으로 푸시되므로 응용 프로그램 전체에서 사용할 수 있습니다. 또한 새 개체를 인스턴스화하는 데 사용되는 $get 메서드가 있습니다.

다음과 같이 볼 수 있습니다. 싱글 톤은 속성 및 메서드를 설정 및 데이터로 설정하여 응용 프로그램을로드 할 때 설정 한 다음 해당 설정 및 데이터를 사용하는 새 개체를 만들 수 있습니다.

다른 사람이 사용할 수 있도록 모듈을 만드는 경우 각 응용 프로그램의 옵션을 개별적으로 수정해야합니다. 이렇게하면됩니다. 공급자를 구성 할 때 설정 한 사전 설정을 사용하여 공급자를 응용 프로그램에 삽입하고 구성한 다음 필요에 따라 개체를 추출합니다.

다음 우리는 서비스공장 있습니다. 실제로는 provider 이상의 추상화입니다. 여기에 각 용도가 시작하는 기능입니다 factory :

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

그것은 단지 provider하지만 오히려 우리가 본 모든 속성을 가진 객체를 반환하는 것보다, 그냥 $get 방법으로 개체를 반환하지 않습니다 provider과 같은 다른 변경 가능한 부분이 있어야합니다. 여기

service위한 기능입니다 : 여기

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

우리가 그 $get 방법 싱글을 반환 각도에 의해 인스턴스화, 제공된 생성자를 사용하여 공장을 가지고. 따라서 앱 전체에서 사용할 수있는 싱글 톤 (singleton)을 가졌으므로 어디에서나 메서드를 사용할 수 있습니다. 한 곳에서 속성을 설정하고 앱에서 다른 곳에서 설정 한 값과 동일한 값을 볼 수 있습니다.이 값은 삽입 할 때마다 동일한 싱글 톤 객체이므로 동일합니다.

요약 :

의 주요 차이점은 service 당신이 서비스를 선언 할 때 당신이 그것을 줄 생성자에서 각도에 의해 생성 된 객체이며, factory 당신이 새를 만드는 데 사용할 수있는 단지 함수라는 것이다 객체와 마찬가지로, 네이티브 자바 스크립트에서와 마찬가지입니다.

호프가 이해하는 데 도움이 되길 바랍니다. factoryservice


로 돌아 가기

귀하의 경우, 각 구성원에 대해 새 오브젝트를 작성하는 데 사용할 팩토리가 있습니다. 당신이 Member을 주입하는 컨트롤러에서, 당신은 간단하게 할 수있는 :

var data = {first_name: "John", last_name: "Smith"} 
var member = new Member(data); 

당신의 공장에 작은 변화와 함께 :

.factory('Member', ['$log', 'DataService', '$http', 'Restangular', 
    function($log, DataService, $http, Restangular) { 
     return function(data) { 
     //construct the object 
     } 
]) 

(생성자로 주입) 공장에 new에 호출을 반환 새롭고 독특한 개체, JS에서 다른 개체와 마찬가지로 구성됩니다. 원하는대로 할 수 있습니다. 컨트롤러 (예 : $rootScope) 또는 회원 및 기타 관련 데이터와 기능이있는 서비스에 두어도됩니다. 그런 다음 원하는 곳 어디서나 앱에 앱을 삽입 할 수 있습니다.

+0

감사합니다. 귀하의 답변과 비디오 (https://egghead.io/lessons/angularjs-providers)는 많은 도움이되었습니다. – jbrown

관련 문제