কৌণিক জেএসে কোনও সম্প্রচার ইভেন্টের সদস্যতা বাতিল করতে কীভাবে। Via অন এর মাধ্যমে নিবন্ধিত ফাংশনটি কীভাবে সরাবেন


278

আমি আমার শ্রোতাদের ফাংশনে একটি $ সম্প্রচার ইভেন্ট ব্যবহার করে নিবন্ধিত করেছি

$scope.$on("onViewUpdated", this.callMe);

এবং আমি এই শ্রোতার একটি নির্দিষ্ট ব্যবসার নিয়মের ভিত্তিতে নিবন্ধভুক্ত করতে চাই। তবে আমার সমস্যাটি হ'ল একবার নিবন্ধিত হয়ে গেলে আমি এটি আন-রেজিস্ট্রেশন করতে পারছি না।

অ্যাঙ্গুলারজেএস-এ কোনও নির্দিষ্ট শ্রোতার আন-রেজিস্ট্রেশন করার জন্য কি কোনও পদ্ধতি আছে? এই ইভেন্টটিকে আন-রেজিস্টার্ড করার জন্য $ এর মতো একটি পদ্ধতি অফ-অফ হতে পারে। সুতরাং যে ব্যবসার যুক্তি উপর ভিত্তি করে আমি বলতে পারেন

 $scope.$off("onViewUpdated", this.callMe);

এবং যখন কেউ "অনভিউ আপডেটেড" ইভেন্টটি সম্প্রচার করে তখন এই ফাংশনটি ডাকা হবে।

ধন্যবাদ

সম্পাদনা : আমি শ্রোতাদের অন্য একটি ফাংশন থেকে ডি-নিবন্ধিত করতে চাই। যেখানে আমি এটি নিবন্ধভুক্ত করি না ফাংশন।


2
যে কারও জন্য অবাক হওয়ার জন্য, ফিরে আসা ফাংশনটি এখানে
ফাগনার ব্র্যাক

উত্তর:


477

আপনাকে ফেরত ফাংশনটি সঞ্চয় করতে হবে এবং ইভেন্টটি থেকে সদস্যতা নেওয়ার জন্য এটি কল করতে হবে।

var deregisterListener = $scope.$on("onViewUpdated", callMe);
deregisterListener (); // this will deregister that listener

এটি সোর্স কোডে পাওয়া যায় :) কমপক্ষে 1.0.4। আমি সম্পূর্ণ কোডটি ছোট হওয়ায় পোস্ট করব

/**
  * @param {string} name Event name to listen on.
  * @param {function(event)} listener Function to call when the event is emitted.
  * @returns {function()} Returns a deregistration function for this listener.
  */
$on: function(name, listener) {
    var namedListeners = this.$$listeners[name];
    if (!namedListeners) {
      this.$$listeners[name] = namedListeners = [];
    }
    namedListeners.push(listener);

    return function() {
      namedListeners[indexOf(namedListeners, listener)] = null;
    };
},

এছাড়াও, দস্তাবেজগুলি দেখুন


হ্যাঁ. সোর কোডটি ডিবাগ করার পরে আমি জানতে পেরেছিলাম যে এখানে একটি $$ শ্রোতার অ্যারে রয়েছে যা সমস্ত ইভেন্ট করে এবং আমার বন্ধ ফাংশন তৈরি করে। ধন্যবাদ
হিতেশ.আনেজা

আসল ব্যবহারের ক্ষেত্রে কী কী আপনি নিবন্ধনকরণের প্রদত্ত কৌণিক উপায়টি ব্যবহার করতে পারবেন না? অন্য একটি স্ক্র্যাপে নিবন্ধন করা কি শ্রোতার সৃষ্টি করার সুযোগের সাথে যুক্ত নয়?
লিভিউ টি।

1
হ্যাঁ, আমি আসলে আমার উত্তরটি মুছে ফেলেছি কারণ আমি মানুষকে বিভ্রান্ত করতে চাই না। এটি করার উপযুক্ত উপায় এটি।
বেন লেশ

3
@ লিভিউ: ক্রমবর্ধমান প্রয়োগের ফলে এটি মাথাব্যথা হয়ে উঠবে। এটি কেবল এই ইভেন্টটিই নয় অন্যান্য প্রচুর ইভেন্টও রয়েছে এবং অগত্যা যে আমি সর্বদা একই স্কোপ ফাংশনে ডি-নিবন্ধভুক্ত থাকি। আমি যখন এমন কোনও ফাংশন কল করতে পারি যা এই শ্রোতার নিবন্ধন করছে তবে শ্রোতাকে অন্য কলের সাথে নিবন্ধভুক্ত করছে, এমনকি আমি সেসব ক্ষেত্রে আমার রেফারেন্সটি পাই না যদি না আমি এগুলি আমার আওতার বাইরে সংরক্ষণ করি। সুতরাং আমার বর্তমান বাস্তবায়নের জন্য আমার বাস্তবায়ন আমার কাছে কার্যকর সমাধান বলে মনে হচ্ছে। তবে অ্যাংুলারজেএস কেন এইভাবে এটি করেছে তার কারণগুলি অবশ্যই জানতে চাই।
হিতেশ.আনেজা

2
আমার মনে হয় যে কৌণিকটি এটি এইভাবে করেছিল কারণ প্রচুর সময় ইনলাইন বেনামে ফাংশন $ অন ফাংশনে যুক্তি হিসাবে ব্যবহৃত হয়। $ সুযোগ। $ বন্ধ (টাইপ, ফাংশন) কল করার জন্য আমাদের বেনামি ফাংশনটির একটি রেফারেন্স রাখতে হবে। এটি কেবল ভিন্ন পদ্ধতিতে চিন্তা করছে যে কীভাবে একজন সাধারণভাবে অ্যাকশনস্ক্রিপ্ট বা জাভাতে পর্যবেক্ষণযোগ্য প্যাটার্ন ভাষায় ইভেন্ট শ্রোতাদের যুক্ত / সরিয়ে ফেলতে পারে
ড্যানরোব

60

বেশিরভাগ জবাব দেখে, তারা অতিরিক্ত জটিল বলে মনে হচ্ছে complicated কৌণিক নিবন্ধনবিহীন করার পদ্ধতি তৈরি করেছে।

ফেরত দেওয়া নিবন্ধকরণ ফাংশনটি$on ব্যবহার করুন :

// Register and get a handle to the listener
var listener = $scope.$on('someMessage', function () {
    $log.log("Message received");
});

// Unregister
$scope.$on('$destroy', function () {
    $log.log("Unregistering listener");
    listener();
});

এগুলির মতো সহজ, অনেক উত্তর রয়েছে তবে এটি আরও সংক্ষিপ্ত।
ডেভিড আগুইলার

8
প্রযুক্তিগতভাবে সঠিক, যদিও কিছুটা বিভ্রান্তিকর, $scope.$onতবে নিজে হাতে অনিবন্ধিত হতে হবে না $destroy। এর চেয়ে ভাল উদাহরণ হ'ল এ $rootScope.$on
hgoebl

2
সর্বোত্তম উত্তর তবে সেই শ্রোতার ভিতরে calling নষ্ট করে কেন শ্রোতাকে হত্যা করে সে সম্পর্কে আরও ব্যাখ্যা দেখতে চান।
মোহাম্মদ রফিঘ

1
@ মোহাম্মদরফিঘ শ্রোতাদের $ ধ্বংসের ভিতরে কল করা ঠিক যেখানে আমি এটি স্থাপন করা বেছে নিয়েছি। আমি যদি সঠিকভাবে স্মরণ করি তবে এই কোডটি ছিল যে আমার কাছে একটি নির্দেশ ছিল এবং এটি বুঝতে পেরেছিল যে যখন নির্দেশের সুযোগটি নষ্ট হয়ে যায়, শ্রোতাদের নিবন্ধভুক্ত করা উচিত।
দীর্ঘ

@hgoebl আপনার অর্থ কী তা আমি জানি না। যদি আমার কাছে উদাহরণস্বরূপ, একটি নির্দেশিকা যা একাধিক জায়গায় ব্যবহৃত হয় এবং প্রত্যেকটি একটি ইভেন্টের জন্য শ্রোতার নিবন্ধভুক্ত হয়, তবে কীভাবে আমার সহায়তায় $ রুটস্কোপ using ব্যবহার করবেন? নির্দেশকের স্কোপ নিষ্পত্তি তার শ্রোতাদের নিষ্পত্তি করার জন্য সেরা জায়গা বলে মনে হচ্ছে।
দীর্ঘ

26

এই কোডটি আমার পক্ষে কাজ করে:

$rootScope.$$listeners.nameOfYourEvent=[];

1
$ রুটস্কোপ $$ দেখে শ্রোতার শ্রোতার জীবনচক্রটি পর্যবেক্ষণ করার এবং এটির সাথে পরীক্ষা করার একটি ভাল উপায়।
এক্সএমএল

সহজ এবং দুর্দান্ত দেখাচ্ছে। আমি মনে করি এটির কার্যকারিতা সবেমাত্র সরিয়ে দেওয়া রেফারেন্স। তাই না?
জয় শুক্ল

26
এই সমাধানটি সুপারিশ করা হয় না কারণ $$ শ্রোতা সদস্যটিকে ব্যক্তিগত বলে বিবেচনা করা হয়। আসলে, '$$' উপসর্গ সহ একটি কৌণিক বস্তুর যে কোনও সদস্য কনভেনশন দ্বারা ব্যক্তিগত।
শোভাভনিক

5
আমি এই বিকল্পটি সুপারিশ করব না, কারণ এটি আপনাকে কেবল অপসারণ করতে হবে তা নয়, সমস্ত শ্রোতা সরিয়ে দেয়। স্ক্রিপ্টের অন্য অংশে আপনি যখন অন্য শ্রোতা যুক্ত করেন তখন ভবিষ্যতে সমস্যা হতে পারে।
রেনার প্লেমার

10

সম্পাদনা: এটি করার সঠিক উপায়টি @ লিভিউটির উত্তর!

আপনাকে এ জাতীয় শ্রোতাদের সরিয়ে দেওয়ার জন্য আপনি সর্বদা কৌণিকের সুযোগ বাড়িয়ে দিতে পারেন:

//A little hack to add an $off() method to $scopes.
(function () {
  var injector = angular.injector(['ng']),
      rootScope = injector.get('$rootScope');
      rootScope.constructor.prototype.$off = function(eventName, fn) {
        if(this.$$listeners) {
          var eventArr = this.$$listeners[eventName];
          if(eventArr) {
            for(var i = 0; i < eventArr.length; i++) {
              if(eventArr[i] === fn) {
                eventArr.splice(i, 1);
              }
            }
          }
        }
      }
}());

এটি এখানে কীভাবে কাজ করবে তা এখানে:

  function myEvent() {
    alert('test');
  }
  $scope.$on('test', myEvent);
  $scope.$broadcast('test');
  $scope.$off('test', myEvent);
  $scope.$broadcast('test');

এবং এখানে এটি কর্মের একটি plunker


মোহন মত কাজ! তবে আমি এটিকে কিছুটা সম্পাদনা করে এটিকে
.রুন

এই সমাধান ভালবাসা। অনেক ক্লিনার সমাধানের জন্য তোলে - এত সহজে পড়া সহজ। +1
রিক

7

কোডটি ডিবাগ করার পরে, আমি "ব্লেশ" এর উত্তরের মতো আমার নিজের ফাংশন তৈরি করেছি। তাই আমি এই কি

MyModule = angular.module('FIT', [])
.run(function ($rootScope) {
        // Custom $off function to un-register the listener.
        $rootScope.$off = function (name, listener) {
            var namedListeners = this.$$listeners[name];
            if (namedListeners) {
                // Loop through the array of named listeners and remove them from the array.
                for (var i = 0; i < namedListeners.length; i++) {
                    if (namedListeners[i] === listener) {
                        return namedListeners.splice(i, 1);
                    }
                }
            }
        }
});

সুতরাং আমার ফাংশনটিকে $ রুটস্কোপে সংযুক্ত করে এখন এটি আমার সমস্ত কন্ট্রোলারদের কাছে উপলব্ধ।

এবং আমার কোড আমি করছি

$scope.$off("onViewUpdated", callMe);

ধন্যবাদ

সম্পাদনা: এটি করার কৌণিক জেএস উপায়টি @ লিভিউটির উত্তর! তবে আপনি যদি শ্রোতাকে অন্য স্কোপে ডি-রেজিস্টার করতে চান এবং একই সাথে ডি-রেজিস্ট্রেশন ফাংশনটির রেফারেন্স রাখতে স্থানীয় ভেরিয়েবলগুলি তৈরি থেকে দূরে থাকতে চান। এটি একটি সম্ভাব্য সমাধান।


1
আমি আসলে আমার উত্তরটি মুছে ফেলছি, কারণ @ লিভিউটির উত্তর 100% সঠিক।
বেন লেশ

@blesh LiviuT এর উত্তরটি সঠিক এবং অচলভাবে একটি অ্যানগালার ডি-রেজিস্টার করার পদ্ধতির সরবরাহ করেছে তবে যে পরিস্থিতিতে আপনাকে শ্রোতাদের বিভিন্ন ক্ষেত্রে নন-রেজিস্ট্রেশন করতে হবে এমন পরিস্থিতিতে ভালভাবে জড়িত না। সুতরাং এটি একটি সহজ বিকল্প।
হিতেশ.আনেজা

1
এটি অন্য কোনও সমাধান যেমন হুক আপ প্রদান করে। আপনি কেবলমাত্র একটি বহির্মুখী বন্ধের বা এমনকি বিশ্বব্যাপী সংগ্রহে ... বা আপনি যে কোনও জায়গায় ধ্বংসের কাজটি সহ ভেরিয়েবলটি রেখেছিলেন।
বেন লেশ

ডি-রেজিস্ট্রেশন ফাংশনগুলির রেফারেন্স রাখতে আমি গ্লোবাল ভেরিয়েবলগুলি তৈরি করে রাখতে চাই না এবং আমার নিজস্ব অফ অফ ফাংশনটি ব্যবহার করে আমি কোনও সমস্যা দেখতে পাই না।
হিতেশ.আনেজা

1

@ লিভিউটের উত্তরটি দুর্দান্ত, তবে হ্যান্ডলারের টিয়ার-ডাউন ক্রিয়াকলাপটি অন্য কোনও সুযোগ বা ফাংশন থেকে কীভাবে পুনরায় অ্যাক্সেস করবেন তা ভাবতে ভাবতে অনেক লোক মনে হয়, যদি আপনি এটি তৈরির জায়গা বাদে অন্য কোনও জায়গা থেকে এটি ধ্বংস করতে চান। @। Мусабеков এর উত্তরটি দুর্দান্ত কাজ করে তবে খুব মূর্তিমান নয়। (এবং বেসরকারী প্রয়োগের বিশদ কী হতে পারে, যা যে কোনও সময় পরিবর্তন করতে পারে তার উপর নির্ভর করে)) এবং সেখান থেকে এটি আরও জটিল হয়ে ওঠে ...

আমি মনে করি এখানে সহজ উত্তরটি offCallMeFnহ্যান্ডলারে নিজেই কেবল টিয়ার-ডাউন ফাংশনটির ( তার উদাহরণে) একটি রেফারেন্স বহন করা এবং তারপরে কোনও শর্তের ভিত্তিতে কল করে; সম্ভবত একটি যুক্তি যা আপনি ইভেন্টটি সম্প্রচারিত বা নির্গমন করতে অন্তর্ভুক্ত করেন। হ্যান্ডলাররা এইভাবে নিজেরাই ছিন্ন করতে পারেন, আপনি যখনই চান, যেখানেই চান নিজের ধ্বংসের বীজ বয়ে বেড়াচ্ছেন। তাই ভালো:

// Creation of our handler:
var tearDownFunc = $rootScope.$on('demo-event', function(event, booleanParam) {
    var selfDestruct = tearDownFunc;
    if (booleanParam === false) {
        console.log('This is the routine handler here. I can do your normal handling-type stuff.')
    }
    if (booleanParam === true) {
        console.log("5... 4... 3... 2... 1...")
        selfDestruct();
    }
});

// These two functions are purely for demonstration
window.trigger = function(booleanArg) {
    $scope.$emit('demo-event', booleanArg);
}
window.check = function() {
    // shows us where Angular is stashing our handlers, while they exist
    console.log($rootScope.$$listeners['demo-event'])
};

// Interactive Demo:

>> trigger(false);
// "This is the routine handler here. I can do your normal handling-type stuff."

>> check();
// [function] (So, there's a handler registered at this point.)  

>> trigger(true);
// "5... 4... 3... 2... 1..."

>> check();
// [null] (No more handler.)

>> trigger(false);
// undefined (He's dead, Jim.)

দুটি চিন্তা:

  1. এটি একবার রান হ্যান্ডলারের দুর্দান্ত সূত্র। শর্তসাপেক্ষে কেবল ড্রপ করুন এবং selfDestructএটি আত্মঘাতী মিশনটি শেষ করার সাথে সাথে চালান ।
  2. আমি অবাক হয়েছি যে উত্সের সুযোগটি কখনই যথাযথভাবে ধ্বংস হয়ে যায় এবং আবর্জনা-সংগৃহীত হবে, আপনি ক্লোরোড ভেরিয়েবলের রেফারেন্স বহন করে রেখেছেন। আপনার এটির একটি মিলিয়ন ব্যবহার করতে হবে এমনকি এটির স্মৃতি সমস্যা হতে পারে তবে আমি কৌতূহলী। কারও কোন অন্তর্দৃষ্টি থাকলে দয়া করে শেয়ার করুন।

1

উপাদানটি সরানো হলে আপনার শ্রোতাদের সদস্যতা ত্যাগ করতে একটি হুক রেজিস্টার করুন:

$scope.$on('$destroy', function () {
   delete $rootScope.$$listeners["youreventname"];
});  

এটি করার জন্য সাধারণত-স্বীকৃত উপায় না হলেও, অনেক সময় রয়েছে এটির প্রয়োজনীয় সমাধান।
টনি ব্রাসুনাস

1

আপনার যদি শ্রোতাকে একাধিকবার চালু এবং বন্ধ করতে হয় তবে আপনি booleanপরামিতি সহ একটি ফাংশন তৈরি করতে পারেন

function switchListen(_switch) {
    if (_switch) {
      $scope.$on("onViewUpdated", this.callMe);
    } else {
      $rootScope.$$listeners.onViewUpdated = [];
    }
}

0

'$ অন' নিজেই নিবন্ধনবিহীন হয়ে ফাংশন দেয়

 var unregister=  $rootScope.$on('$stateChangeStart',
            function(event, toState, toParams, fromState, fromParams, options) { 
                alert('state changing'); 
            });

আপনি সেই শ্রোতার নিবন্ধন করতে নিবন্ধভুক্ত () ফাংশনটি কল করতে পারেন


0

একটি উপায় হ'ল শ্রোতার সাথে এটি শেষ হয়ে গেলে কেবল তা ধ্বংস করা।

var removeListener = $scope.$on('navBarRight-ready', function () {
        $rootScope.$broadcast('workerProfile-display', $scope.worker)
        removeListener(); //destroy the listener
    })
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.