$ rootScope. $ broadcast vs. $ scope. $ emit


349

이제 사이의 성능 차이 있음 $broadcast과이 $emit제거 된 선호 할 이유가 $scope.$emit에가 $rootScope.$broadcast?

그들은 다릅니다.

$emit 범위 계층 (위쪽)으로 제한됩니다-디자인에 맞으면 좋을 수도 있지만 다소 임의적 인 제한으로 보입니다.

$rootScope.$broadcast이벤트를 듣도록 선택한 모든 사람에 대해 작동합니다 . 이는 제 생각에보다 합리적인 제한입니다.

뭔가 빠졌습니까?

편집하다:

답변에 대한 답변으로 명확히하기 위해 디스패치의 방향은 내가 추구하는 문제가 아닙니다. $scope.$emit이벤트를 위쪽 및 $scope.$broadcast아래쪽 으로 전달합니다 . 그러나 항상 $rootScope.$broadcast모든 의도 된 청취자에게 도달하기 위해 사용하지 않는 이유 는 무엇입니까?


답변:


1155

tl; dr (이 tl; dr는 아래 @ sp00m 의 답변입니다)

$emit이벤트를 위로 $broadcast파견 ... 이벤트를 아래로 파견

상해

$rootScope.$emit다른 $rootScope청취자 만 잡을 수 있습니다. 이것은 당신이 $scope그것을 얻기를 원하지 않을 때 좋습니다 . 주로 높은 수준의 커뮤니케이션. 아이들이들을 수 없도록 어른들이 방에서 서로 이야기하는 것으로 생각하십시오.

$rootScope.$broadcast거의 모든 것이들을 수있는 방법입니다. 이것은 저녁 식사가 준비되었다고 소리 치는 부모와 동일 할 것입니다.

$scope.$emit당신이 그 $scope모든 부모님을 원하고 $rootScope행사를 듣는 때입니다. 이것은 집에서 부모에게 물고있는 아이입니다 (그러나 다른 아이들이들을 수있는 식료품 점에서는 아닙니다).

$scope.$broadcast을위한 $scope자신과 아이들. 부모님이들을 수없는 박제 된 동물에게 속삭이는 아이입니다.


3
@NewDev 이유는 종종 페이지에서 범위를 반복하기 때문입니다. 서로 다른 데이터 인스턴스를 나타내는 두 개 이상의 범위가있는 경우 (예 : 각각 자체 범위가있는 페이지의 환자 레코드 목록) 해당 루트 중 하나를 대상으로하는 이벤트를 루트에서 브로드 캐스트하는 것은 작동하지 않습니다. 범위. $rootScope가능한 경우 브로드 캐스트를 피 하면 더 나은 재사용이 가능합니다.
Tim Rogers

4
당신이 말한 것은 잘못이 아니지만 $ emit이 문서를 하위 범위로 내려 놓고 $ emit이 문서를 상위 범위로 올리도록 일반화하는 방법입니다. 둘 다 현재 범위에 연결된 리스너를 트리거합니다.
Eric

123
사용한 예가 훌륭합니다!
Assaf

72
와! 아이들도 이것을 이해할 수 있습니다! 놀라운 :)
Navaneeth

3
완벽한 예, 설명을 사랑하십시오
Robin-Hoodie

104

동일한 작업을 수행하지 않습니다 . 범위 계층 구조를 통해 위쪽으로$emit 이벤트 를 전달하고 모든 하위 범위로 아래쪽 으로 이벤트 를 전달합니다 .$broadcast


2
예, 나는 그 질문에서 (아마도 파견의 방향에 대해 분명히 알 수 있었을 것입니다) 지적했습니다. 그러나 나는 그것이 다소 임의적 인 제한이라고 지적했다. 내 "청취자"에 도달 할 수 있는데 왜 항상 아래에서이 작업을 수행 할 수 $rootScope없습니까?
New Dev

$ emit은 범위의 자식 또는 형제 범위에 영향을 미치지 않기 때문입니다. 이것들은 캡처 및 버블 링과 같은 자바 스크립트의 이벤트 전파 유형에 매핑됩니다. $ broadcast는 캡처에 사용되고 $ emit은 버블 링에 사용됩니다. 꽤 잘 차이를 설명하는 지금 보이는 고대 쿼크 모드 기사가있다 : quirksmode.org/js/events_order.html
앨런 L.

77

다음 링크에서 다음 그래픽을 만들었습니다. https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

범위, rootScope, 방출, 브로드 캐스트

보다시피, $rootScope.$broadcast보다 많은 청취자를 공격합니다 $scope.$emit.

또한 $scope.$emit버블 링 효과는 취소 할 수 있지만 취소 $rootScope.$broadcast할 수는 없습니다.


24
나는 많은 화살을 본다.
Mars Robertson

4
나는 :) 시각적 인 답변의 팬입니다 @MichalStefanow
마리아 이네스 Parnisari

@mparnisari :. $ broadcast (name, args)-모든 어린이의 $ scope를 통해 이벤트를 브로드 캐스트합니다. $ emit (name, args)-$ rootScope를 포함하여 모든 부모에게 $ scope 계층의 이벤트를 내보내십시오
CodeMan

19

여기에 이미지 설명을 입력하십시오

$ scope. $ emit :이 메소드는 이벤트를 위쪽에서 (자식에서 부모로) 전달합니다.

여기에 이미지 설명을 입력하십시오 $ scope. $ broadcast : 메서드는 이벤트를 아래쪽에서 (부모에서 자식으로) 모든 자식 컨트롤러로 전달합니다.

여기에 이미지 설명을 입력하십시오 $ scope. $ on : 일부 이벤트를 수신하기위한 메소드 등록. 해당 이벤트를 수신하는 모든 컨트롤러는 브로드 캐스트 알림을 받거나 자식-부모 계층 구조에 맞는 위치에 따라 방출합니다.

$ emit 이벤트는 이벤트를 듣고있는 $ scope 중 하나에 의해 취소 될 수 있습니다.

$ on은 "stopPropagation"메소드를 제공합니다. 이 메소드를 호출하면 이벤트 전파가 더 이상 중지되지 않을 수 있습니다.

플 런커 : https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/

형제 범위 (직접 부모-자식 계층 구조에없는 범위)의 경우 $ emit 및 $ broadcast는 형제 범위와 통신하지 않습니다.

여기에 이미지 설명을 입력하십시오

자세한 내용은 http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html을 참조하십시오.


솔루션에 대한 링크는 환영하지만 답변없이 유용한 답변을 얻으십시오 . 링크 주위에 컨텍스트를 추가 하여 동료 사용자가 그 이유와 그 이유를 파악한 다음 페이지의 가장 관련성이 높은 부분을 인용하십시오. 대상 페이지를 사용할 수없는 경우 다시 연결 링크에 불과한 답변은 삭제 될 수 있습니다.
Baum mit Augen

목표는 작동하는 플런저를 제공하는 것이었지만 여기에 적절한 설명을 추가했습니다.
Yogesh

3

@Eddie는 질문에 대한 완벽한 답변을 제공했습니다. 그러나 Pub / Sub의보다 효율적인 접근 방식을 사용하여 주목하고 싶습니다.

마찬가지로 , 대답은 제안

$ broadcast / $ on 접근 방식은 모든 범위 (Scope 계층의 한 방향 또는 양방향으로)에 브로드 캐스트하므로 매우 효율적이지 않습니다. Pub / Sub 접근 방식이 훨씬 직접적입니다. 구독자 만 이벤트를 수신하므로 시스템의 모든 범위에서 작동하지는 않습니다.

angular-PubSub각도 모듈을 사용할 수 있습니다 . PubSub앱 종속성 에 모듈을 추가 하면 PubSub서비스를 사용 하여 이벤트 / 주제를 구독 및 구독 취소 할 수 있습니다.

구독하기 쉬운 :

// Subscribe to event
var sub = PubSub.subscribe('event-name', function(topic, data){

});

손쉬운 게시

PubSub.publish('event-name', {
    prop1: value1,
    prop2: value2
});

구독을 취소하려면 PubSub.unsubscribe(sub);OR을 사용하십시오 PubSub.unsubscribe('event-name');.

참고 메모리 누수를 피하기 위해 구독 취소하는 것을 잊지 마십시오.


2

서비스에서 RxJS 사용

예를 들어 상태를 유지하는 서비스가있는 상황은 어떻습니까? 해당 서비스에 변경 사항을 적용 할 수 있고 페이지의 다른 임의의 구성 요소가 그러한 변경 사항을 어떻게 알 수 있습니까? 요즘이 문제를 해결하는 데 어려움을 겪고 있습니다.

RxJS Extensions for Angular 로 서비스를 빌드하십시오 .

<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/rx/dist/rx.all.js"></script>
<script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>
var app = angular.module('myApp', ['rx']);

app.factory("DataService", function(rx) {
  var subject = new rx.Subject(); 
  var data = "Initial";

  return {
      set: function set(d){
        data = d;
        subject.onNext(d);
      },
      get: function get() {
        return data;
      },
      subscribe: function (o) {
         return subject.subscribe(o);
      }
  };
});

그런 다음 변경 사항을 구독하십시오.

app.controller('displayCtrl', function(DataService) {
  var $ctrl = this;

  $ctrl.data = DataService.get();
  var subscription = DataService.subscribe(function onNext(d) {
      $ctrl.data = d;
  });

  this.$onDestroy = function() {
      subscription.dispose();
  };
});

고객은로 변경 사항을 구독 할 수 DataService.subscribe있으며 생산자는로 변경 사항을 푸시 할 수 있습니다 DataService.set.

PLNKR데모 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.