2017-01-03 6 views
1

私はアプリケーションのために働いています。Angular jをサードパーティのjsライブラリと通信したいと思います。このために、私はmediator 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です: Plunkr

このplunkerをテストするには:

  1. 実行plunker。
  2. 開発者コンソールを開きます。火災イベント

上の最初のページに

  • 2ページ目の最初のページをクリックし
  • クリックして火災のイベント
  • クリック
  • クリック
  • クリックして、あなたは最初のページに二回目をナビゲートするとして、イベントを再度購読し、2回発射する。これは、最初のページに複数回移動すると、複数回購読します。

    私が間違っているかどうか教えてください。

  • +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は、上記のものに完全にうまく使えます。 –

    関連する問題