Angular.js에서 어떤 "사물"을 다른 사람에게 주입 할 수 있습니까?


142

Angular의 Dependency Injection을 이해하는 데 약간의 어려움이 있습니다. 그래서 제 질문은 누구나 컨트롤러, 팩토리, 프로 바이더 등과 같은 "유형"중 어떤 것이 동일한 "유형"의 다른 인스턴스를 포함하여 다른 유형에 주입 할 수 있는지 설명 할 수 있습니까?

내가 실제로 찾고있는 것은 y / n으로 채워진이 테이블입니다. 동일한 행 / 열을 가진 셀의 경우, 이는 하나의 "유형"값을 동일한 "유형"을 가진 다른 유형으로 주입하는 것을 의미합니다.

+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Constant       |          |            |           |         |        |          |         |       |
| Controller     |          |            |           |         |        |          |         |       |
| Directive      |          |            |           |         |        |          |         |       |
| Factory        |          |            |           |         |        |          |         |       |
| Filter         |          |            |           |         |        |          |         |       |
| Provider       |          |            |           |         |        |          |         |       |
| Service        |          |            |           |         |        |          |         |       |
| Value          |          |            |           |         |        |          |         |       |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+

답변:


391

설명없이 "예"와 "아니오"로 표를 채우는 대신 조금 더 자세히 설명하겠습니다.

[참고, 마무리 후 추가 : 이것은 예상보다 훨씬 길어졌습니다. 하단에 tl; dr이 있지만 이것이 정보를 제공하기를 바랍니다.]

[이 답변은 AngularJS 위키에 추가되었습니다 : Dependency Injection 이해하기 ]


공급자 ( $provide)

$provide서비스는 Angular에게 새로운 주사 가능한 물건을 만드는 방법을 알려주는 역할을합니다. 이러한 것을 서비스 라고 합니다 . 서비스는 공급자 라고하는 것으로 정의되며 , 이는 사용시 생성하는 것 $provide입니다. 공급자 정의는 서비스의 provider메소드를 통해 수행되며 응용 프로그램 기능에 서비스를 주입하도록 요청 $provide하여 $provide서비스를 유지할 수 있습니다 config. 예를 들면 다음과 같습니다.

app.config(function($provide) {
  $provide.provider('greeting', function() {
    this.$get = function() {
      return function(name) {
        alert("Hello, " + name);
      };
    };
  });
});

여기에 서비스라는 새로운 공급자를 정의했습니다 greeting. 우리는 greeting컨트롤러와 같은 주입 가능한 함수에 명명 된 변수를 주입 할 수 있으며 Angular는 $get서비스의 새로운 인스턴스를 반환하기 위해 공급자의 함수를 호출합니다 . 이 경우 주입되는 것은 이름에 따라 name매개 변수와 alertsa 메시지를 받는 함수입니다 . 우리는 이것을 다음과 같이 사용할 수 있습니다 :

app.controller('MainController', function($scope, greeting) {
  $scope.onClick = function() {
    greeting('Ford Prefect');
  };
});

이제 트릭이 있습니다. factory, servicevalue공급자의 다양한 부분을 정의하는 모든 단지 바로 가기입니다 - 그들은 모두 그 물건의 출력을 입력 할 필요없이 공급자를 정의하는 방법을 제공한다. 예를 들어 다음 과 같이 정확히 동일한 제공자를 작성할 수 있습니다 .

app.config(function($provide) {
  $provide.factory('greeting', function() {
    return function(name) {
      alert("Hello, " + name);
    };
  });
});

이해하는 것이 중요하므로 다시 말하겠습니다. AngularJS는 위에서 우리가 위에서 작성한 것과 동일한 코드 ( $provide.provider버전) 호출합니다 . 문자 그대로 두 버전에는 100 % 차이가 없습니다. 함수 (일명 함수) value에서 반환하는 것이 항상 동일하면을 사용하여 더 적은 코드를 작성할 수 있습니다 . 예를 들어, 서비스에 대해 항상 동일한 함수를 반환하므로 이를 정의하는 데 사용할 수도 있습니다 .$getfactoryvaluegreetingvalue

app.config(function($provide) {
  $provide.value('greeting', function(name) {
    alert("Hello, " + name);
  });
});

다시 말하지만이 함수를 정의하는 데 사용한 다른 두 가지 방법과 100 % 동일합니다. 이는 입력 내용을 저장하는 방법 일뿐입니다.

이제 app.config(function($provide) { ... })내가 사용하고있는 이 성가신 것을 보셨을 것입니다. 위의 주어진 방법 하나 를 통해 새 공급자를 정의하는 것이 일반적이므로 AngularJS는 $provider모듈 객체에 직접 메서드를 노출하여 더 많은 입력을 저장합니다.

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

myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);

이것들은 모두 app.config(...)우리가 이전에 사용한 더 장황한 버전 과 같은 일을합니다 .

지금까지 건너 뛴 주사 가능한 것은 constant입니다. 지금은 마치 똑같이 작동한다고 말하기 쉽습니다 value. 나중에 한 가지 차이점이 있습니다.

검토 , 모든 코드의이 조각은 일을 정확히 같은 일을 :

myMod.provider('greeting', function() {
  this.$get = function() {
    return function(name) {
      alert("Hello, " + name);
    };
  };
});

myMod.factory('greeting', function() {
  return function(name) {
    alert("Hello, " + name);
  };
});

myMod.value('greeting', function(name) {
  alert("Hello, " + name);
});

인젝터 ( $injector)

인젝터는 우리가 제공 한 코드를 사용하여 실제로 서비스 인스턴스를 생성 할 책임이 있습니다 $provide. 주입 된 인수를 취하는 함수를 작성할 때마다 인젝터가 작동하는 것을 볼 수 있습니다. 각 AngularJS 애플리케이션에는 $injector애플리케이션이 처음 시작될 때 생성 되는 단일 애플리케이션이 있습니다. $injector주사 가능한 기능 에 주사 하여 그것을 붙잡을 수 있습니다 (예, $injector스스로 주사하는 방법을 알고 있습니다!)

이 있으면 $injector서비스 get이름으로 서비스를 호출하여 정의 된 서비스의 인스턴스를 얻을 수 있습니다 . 예를 들어

var greeting = $injector.get('greeting');
greeting('Ford Prefect');

인젝터는 또한 서비스를 기능에 주입하는 역할을합니다. 예를 들어, 인젝터의 invoke방법을 사용하는 모든 기능에 서비스를 마법으로 주입 할 수 있습니다 .

var myFunction = function(greeting) {
  greeting('Ford Prefect');
};
$injector.invoke(myFunction);

인젝터가 서비스 인스턴스를 한 번만 작성한다는 점은 주목할 가치가 있습니다 . 그런 다음 공급자가 서비스 이름으로 반환하는 모든 것을 캐시합니다. 다음에 서비스를 요청할 때 실제로 동일한 객체를 얻게됩니다.

따라서 질문에 대답하기 위해 로 호출$injector.invoke 되는 모든 함수에 서비스를 삽입 할 수 있습니다 . 여기에는

  • 컨트롤러 정의 기능
  • 지시문 정의 함수
  • 필터 정의 기능
  • $get공급자 의 방법 (일명 factory정의 기능)

이후 constant의와는 value항상 정적 값을 반환 S, 그들이 인젝터를 통해 호출하고 있지 않습니다 따라서 당신은 그 주사한다 아무것도 할 수 없습니다.

공급자 구성

누군가가 함께 본격적인 제공자를 설정하는 귀찮게 왜 당신이 궁금 할 provide방법 경우 factory, value훨씬 쉽게, 등. 답은 공급자가 많은 구성을 허용한다는 것입니다. 공급자를 통해 서비스를 만들거나 Angular가 제공하는 바로 가기 중 하나를 사용하면 해당 서비스 구성 방법을 정의하는 새 공급자를 만듭니다. 내가 언급 하지 않은 것은 이러한 공급자를 config응용 프로그램의 섹션에 삽입하여 상호 작용할 수 있다는 것입니다.

먼저 Angular는 애플리케이션을 2 단계 ( configrun단계)로 실행합니다 . config당신은 필요에 따라 어떤 업체를 설정할 수있는 단계는 우리가 본대로이다. 지시어, 컨트롤러, 필터 등이 설정되는 곳이기도합니다. run당신이 생각 하듯이 각도가 실제로 DOM을 컴파일하고 응용 프로그램을 시작하는 위치 단계는,이다.

myMod.configmyMod.run기능을 사용하여 이러한 단계에서 실행할 추가 코드를 추가 할 수 있습니다. 각 단계는 특정 단계에서 실행할 기능을 수행합니다. 첫 번째 섹션에서 보았 듯이 이러한 함수는 삽입 가능합니다 $provide. 첫 번째 코드 샘플에 기본 제공 서비스를 주입했습니다 . 그러나 주목할 가치가있는 것은 단계 동안config ( AUTO모듈 의 서비스를 제외 $provide하고 $injector) 제공자 만 주입 할 수 있다는 것 입니다.

예를 들어 다음은 허용되지 않습니다 .

myMod.config(function(greeting) {
  // WON'T WORK -- greeting is an *instance* of a service.
  // Only providers for services can be injected in config blocks.
});

귀하 가 액세스 할 있는 것은 귀하 가 만든 서비스 제공 업체 입니다.

myMod.config(function(greetingProvider) {
  // a-ok!
});

한 가지 중요한 예외가 있습니다. constants는 변경할 수 없으므로 config블록 내부에 주입 될 수 있습니다 (이는 values 와 다른 점입니다 ). 이름만으로 액세스 할 수 있습니다 ( Provider접미사가 필요 하지 않음 ).

서비스 제공자를 정의 할 때마다 해당 제공자 의 이름 이로 지정됩니다 serviceProvider. 여기서 service서비스 이름입니다. 이제 우리는 공급자의 힘을 사용하여 좀 더 복잡한 일을 할 수 있습니다!

myMod.provider('greeting', function() {
  var text = 'Hello, ';

  this.setText = function(value) {
    text = value;
  };

  this.$get = function() {
    return function(name) {
      alert(text + name);
    };
  };
});

myMod.config(function(greetingProvider) {
  greetingProvider.setText("Howdy there, ");
});

myMod.run(function(greeting) {
  greeting('Ford Prefect');
});

이제 우리는 제공자 setText를 정의하는 데 사용할 수 있는 기능을 제공 합니다 alert. config이 메소드를 호출하고 서비스를 사용자 정의하기 위해 블록 으로이 제공자에 액세스 할 수 있습니다 . 앱을 마지막으로 실행하면 greeting서비스를 가져 와서 사용자 지정이 적용되었는지 확인할 수 있습니다.

이것은 더 복잡한 예이므로 다음은 실제 데모입니다. http://jsfiddle.net/BinaryMuse/9GjYg/

컨트롤러 ( $controller)

컨트롤러 기능은 삽입 할 수 있지만 컨트롤러 자체는 다른 것에 주입 할 수 없습니다. 공급자를 통해 컨트롤러가 생성되지 않기 때문입니다. 대신, $controller컨트롤러 설정을 담당 하는 내장 Angular 서비스 가 있습니다. 에 전화 하면 마지막 섹션과 마찬가지로 myMod.controller(...)실제로이 서비스 제공 업체에 액세스 하는 것입니다.

예를 들어 다음과 같이 컨트롤러를 정의 할 때 :

myMod.controller('MainController', function($scope) {
  // ...
});

당신이 실제로하고있는 것은 이것입니다 :

myMod.config(function($controllerProvider) {
  $controllerProvider.register('MainController', function($scope) {
    // ...
  });
});

나중에 Angular는 컨트롤러의 인스턴스를 만들어야 할 때 $controller서비스를 사용합니다 (이를 사용 $injector하여 컨트롤러 기능을 호출하여 종속성을 주입합니다).

필터와 지시어

filterdirective작업 정확히 같은 방법으로 controller; filter호출 된 서비스 사용 $filter및 제공 $filterProvider, 동안 directive서비스가 전화 사용 $compile과 그 제공자를 $compileProvider. 일부 링크 :

다른 예에 따라, myMod.filter그리고 myMod.directive이러한 서비스를 구성하는 단축키입니다.


tl; dr

요약하자면로 호출되는 모든 함수를에 $injector.invoke 삽입 할 수 있습니다 . 여기에는 차트의 내용이 포함되지만 이에 국한되지는 않습니다.

  • 제어 장치
  • 지령
  • 공장
  • 필터
  • 공급자 $get(제공자를 객체로 정의 할 때)
  • 프로 바이더 함수 (프로 바이더를 생성자 함수로 정의 할 때)
  • 서비스

공급자 는 사물에 주입 할 수있는 새로운 서비스 만듭니다 . 여기에는 다음이 포함됩니다.

  • 일정한
  • 공장
  • 공급자
  • 서비스

즉 같은 서비스 내장 말했다 $controller$filter 주입, 당신은 할 수 사용 , 그 자체로 당신이 그 방법 (사용자가 정의한 일을하지 않더라도 정의 새로운 필터와 컨트롤러를 잡아 그 서비스를 할 수가되게합니다 사물에 주입).

그 외에 인젝터 호출 기능에는 제공자가 제공 한 서비스를 주입 할 수 있습니다 . 여기 에는 제한이 없습니다 ( 여기에 나열된 configrun차이점 제외).


6
와! 자세한 답변 시간을 내 주셔서 감사합니다! 나는 이것을 두 번 읽었고 꽤 이해했다고 생각합니다. 오늘 나중에 그 내용과 그 링크를 자세히 살펴볼 것입니다. 그리고 고양이를위한 또 다른 +1. :)
user1527166

18
내가 본 가장 유용하고 자세한 SO 답변 중 하나-감사합니다!
Godders

11
이 답변은 새로운 차원의 최고를 정의합니다. 조명 물건.
Ngure Nyaga

4
지금까지 AngularJS에서 가장 좋은 리소스를 찾았습니다. 감사.
code90

5
문자 그대로 내가 본 AngularJS 문서 중 최고의 조각입니다. 잘 했어!
Iain Duncan

13

BinaryMuse가 제공 업체, 공장 및 서비스에 대한 놀라운 답변을 제시하는 점은 모두 똑같이 중요합니다.

아래는 그녀의 요점을 시각적으로 설명 할 수있는 이미지입니다.

AngularJS는 모두 공급자 일뿐입니다
(출처 : simplygoodcode.com )


7

Michelle의 훌륭한 답변. 지시어 를 주입 할 수 있다고 지적하고 싶습니다 . 당신이 지시라는 한 경우 myThing, 당신은 그것을 주입 할 수 있습니다 myThingDirective: 여기에 인위적인 예입니다 .

위의 예제는 실용적이지는 않지만 지시문을 삽입하는 기능은 해당 지시문을 꾸미고 싶을 때 유용 합니다 .


지시문을 장식하는 두 번째 예 는 Angular 1.4 이후 작동하지 않는 것 같습니다 . ( Juan Biscaia의 의견 참조 )
Vadorequest
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.