프로그래밍 언어/HTML,CSS,JS

AngularJS에서 컨트롤러간에 통신하는 올바른 방법

Rateye 2021. 9. 27. 10:38
728x90
반응형
질문 : AngularJS에서 컨트롤러간에 통신하는 올바른 방법은 무엇입니까?

컨트롤러간에 통신하는 올바른 방법은 무엇입니까?

window 관련된 끔찍한 퍼지를 사용하고 있습니다.

function StockSubgroupCtrl($scope, $http) {
    $scope.subgroups = [];
    $scope.handleSubgroupsLoaded = function(data, status) {
        $scope.subgroups = data;
    }
    $scope.fetch = function(prod_grp) {
        $http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
    }
    window.fetchStockSubgroups = $scope.fetch;
}

function StockGroupCtrl($scope, $http) {
    ...
    $scope.select = function(prod_grp) {
        $scope.selectedGroup = prod_grp;
        window.fetchStockSubgroups(prod_grp);
    }
}
답변

편집 :이 답변에서 해결 된 문제는 angular.js 버전 1.2.7 에서 해결되었습니다. $broadcast 이제 등록되지 않은 범위에 대한 버블 링을 방지하고 $ emit만큼 빠르게 실행됩니다.

$ broadcast 공연은 angular 1.2.16의 $ emit과 동일합니다.

이제 다음을 수행 할 수 있습니다.

  • $rootScope 에서 $broadcast 사용
  • 이벤트에 대해 알아야 하는 로컬 $scope $on 을 사용하여 수신

아래의 원래 답변

$rootScope.$broadcast + $scope.$on 대신 $rootScope.$emit + $rootScope.$on 좋습니다. 전자는 @numan이 제기 한 심각한 성능 문제를 일으킬 수 있습니다. 이벤트가 모든 범위를 통해 버블 링되기 때문입니다.

그러나 후자 ( $rootScope.$emit + $rootScope.$on )는이 문제를 겪지 않으므로 빠른 통신 채널로 사용할 수 있습니다!

$emit 의 각도 문서에서 :

스코프 계층을 통해 이벤트 이름을 위쪽으로 전달하여 등록 된

$rootScope 범위가 없기 때문에 버블 링이 발생하지 않습니다. $rootScope.$emit() / $rootScope.$on() 을 EventBus로 사용하는 것이 완전히 안전합니다.

그러나 컨트롤러 내에서 사용할 때 한 가지 문제가 있습니다. $rootScope.$on() 직접 바인딩하는 $scope 가 파괴 될 때 직접 바인딩을 정리해야합니다. 이는 컨트롤러 (서비스와 달리)가 애플리케이션의 수명 동안 여러 번 인스턴스화 될 수 있기 때문에 바인딩이 합산되어 결국 모든 곳에서 메모리 누수가 발생합니다. :)

등록을 취소하려면 $scope$destroy $rootScope.$on 에서 반환 한 함수를 호출하면됩니다.

angular
    .module('MyApp')
    .controller('MyController', ['$scope', '$rootScope', function MyController($scope, $rootScope) {

            var unbind = $rootScope.$on('someComponent.someCrazyEvent', function(){
                console.log('foo');
            });

            $scope.$on('$destroy', unbind);
        }
    ]);

다른 EventBus 구현에도 적용되므로 리소스를 정리해야하는 것은 실제로 각도에 특정한 것이 아닙니다.

그러나 그러한 경우에는 삶을 더 쉽게 만들 수 있습니다. 예를 들어 $rootScope 패치하고 $onRootScope 에서 발생하는 이벤트를 구독 $scope 가 파괴 될 때 처리기를 직접 $rootScope

$onRootScope 메서드를 제공하기 위해 $rootScope 를 원숭이 패치하는 가장 깨끗한 방법은 데코레이터를 사용하는 것입니다 (실행 블록도 잘 수행 할 수 있지만 pssst, 아무에게도 말하지 마십시오).

$scope $onRootScope 속성이 예기치 않게 표시되지 않도록하기 위해 Object.defineProperty() 하고 enumerablefalse 설정합니다. ES5 shim이 필요할 수 있습니다.

angular
    .module('MyApp')
    .config(['$provide', function($provide){
        $provide.decorator('$rootScope', ['$delegate', function($delegate){

            Object.defineProperty($delegate.constructor.prototype, '$onRootScope', {
                value: function(name, listener){
                    var unsubscribe = $delegate.$on(name, listener);
                    this.$on('$destroy', unsubscribe);

                    return unsubscribe;
                },
                enumerable: false
            });


            return $delegate;
        }]);
    }]);

이 방법을 사용하면 위의 컨트롤러 코드를 다음과 같이 단순화 할 수 있습니다.

angular
    .module('MyApp')
    .controller('MyController', ['$scope', function MyController($scope) {

            $scope.$onRootScope('someComponent.someCrazyEvent', function(){
                console.log('foo');
            });
        }
    ]);

따라서이 모든 것의 최종 결과로 $rootScope.$emit + $scope.$onRootScope .

Btw, 저는 앵귤러 팀이 앵귤러 코어 내의 문제를 해결하도록 설득하려고합니다. 여기에서 진행중인 토론이 있습니다 : https://github.com/angular/angular.js/issues/4574

$broadcast $scope 사용하여 적절한 시나리오에서 테이블에 미치는 성능 영향을 보여주는 jsperf입니다.

http://jsperf.com/rootscope-emit-vs-rootscope-broadcast

jsperf 결과

출처 : https://stackoverflow.com/questions/11252780/whats-the-correct-way-to-communicate-between-controllers-in-angularjs
728x90
반응형