2017-01-03 1 views
1

저는 응용 프로그램을 위해 일하고 있으며 Angular js를 제 3 자 js 라이브러리와 통신하려고합니다. 이를 위해 중재자 js를 사용하는 pubsub 메서드를 사용했습니다. 하지만이 때문에 어떤 이벤트에 가입하면 여러 번 구독하게되고 이벤트로 인해 여러 번 게시됩니다.Angular js가 여러 번 구독하고 여러 이벤트가 발생합니다.

가 나는 코드 아래 사용했다 :

여기
angular.module('app') 
    .service('mediator', function() { 
    var mediator = window.mediator || new Mediator(); 
    return mediator; 
}); 

// Main controller begins here 
    angular.module('app').controller('MainController', MainController); 
    MainController.$inject = ['mediator']; 

    function MainController(mediator){ 
    var vm = this; 
    vm.title = "This is main controller." 

    vm.sendMessage = function(){ 
     mediator.publish('something', { data: 'Some data' }); 
    } 


    } 


    // First page controller begins here 
    angular.module('app').controller('FirstController', FirstController); 
    FirstController.$inject = ['mediator']; 

    function FirstController(mediator){ 
    var vm = this; 

    console.log('Subscribed events for first controller.'); 

    var counter = 0; 
    mediator.subscribe('something', function(data){ 
     console.log('Fired event for '+ counter.toString()); 
     counter = counter + 1; 
    }); 

    } 

더 나은 설명은 plunker입니다 :

  1. 실행 plunker : Plunkr

    이 plunker을 테스트합니다.

  2. 개발자 콘솔을 엽니 다. 첫 페이지에
  3. 클릭
  4. 클릭 화재 이벤트
  5. 초 페이지를 클릭
  6. 첫 페이지에
  7. 클릭
  8. 화재 이벤트에
  9. 클릭

당신은 첫 페이지 두 번째로 이동, 그것은을 이벤트를 다시 구독하고 두 번 발동합니다. 첫 페이지를 여러 번 탐색하면 여러 번 구독하게됩니다.

내가 잘못했는지 알려주세요.

+0

컨트롤러를로드 할 때마다 현재 페이지를 탐색 할 때마다 구독하게됩니다. 이것은 구독 여부에 관계없이 'if (! subscribed)'또는 이와 유사한 방식으로 추적하는 간단한 경우처럼 보입니다. – Claies

+1

글쎄, 당신은 당신의 컨트롤러가 파괴되면 구독을 취소하지 않을거야. 따라서 구독을 계속합니다. 여러 콘솔 로그뿐만 아니라 좋은 메모리 누수가 있습니다. –

+0

@JBNizet : 중재자 js를 사용하여 이벤트 구독을 취소하는 방법을 알려주십시오. –

답변

1

컨트롤러가 파괴되면 구독을 취소 할 수 있습니다. 컨트롤러가 제거 될 때

var sub = function(data){ 
    console.log('Fired event for '+ counter.toString()); 
    counter = counter + 1; 
} 
mediator.subscribe('something', sub); 

그런 다음 당신은 알림을 수신 거부 할 각 이벤트를 사용할 수 있습니다 :

이 사용 중재자를하려면 먼저 구독 기능을 저장해야

$scope.$on("$destroy", function() { 
    mediator.remove("something", sub); 
}); 

이 패턴을 사용할 때마다 중복을 이유로 구독을 제거해야하는 순간을 고려해야하며 메모리 누수가 발생할 수 있습니다.

angular.module('app').controller('FirstController', FirstController); 
FirstController.$inject = ['mediator', '$scope']; 

Plunkr 예 :

당신은 또한 $ 범위를 주입 할 필요가 잊지 마세요 (모델의 홀더로 사용하지 않는 경우에도, 그것은 이벤트 리스너를 등록하는 그것을 사용하는 괜찮습니다) https://plnkr.co/edit/CgYLLSxGF2Fww5vBB7PB

희망이 있습니다.

+0

내 코드에서 $ scope을 사용하고 싶지 않습니다. 뷰 모델 객체 (VM)를 사용하는 방법이 있습니까? –

+0

왜 안 되니? $ scope없이 모델 변경을 직접 관찰 할 방법이 없으므로 $ scope없이 VM 이벤트에 리스너를 등록하는 직접적인 방법이 있는지 확신 할 수 없습니다. 다시 말하지만 컨트롤러를 권장 패턴으로 사용하더라도 각도에 의해 관리되는 범위는 여전히 남아 있습니다. $ scope는 위에서 언급 한 것들을 사용하기에 완벽합니다. –

관련 문제