AngularJS - क्या $ घटना श्रोताओं को नष्ट कर देता है?


200

https://docs.angularjs.org/guide/directive

इस ईवेंट को सुनकर, आप उन ईवेंट श्रोताओं को हटा सकते हैं जो मेमोरी लीक का कारण बन सकते हैं। स्कोप और तत्वों के लिए पंजीकृत श्रोताओं को नष्ट होने पर स्वचालित रूप से साफ किया जाता है, लेकिन अगर आपने किसी श्रोता को किसी सेवा पर पंजीकृत किया है, या किसी DOM नोड पर श्रोता को पंजीकृत किया है जिसे हटाया नहीं जा रहा है, तो आपको इसे स्वयं साफ करना होगा या आप एक मेमोरी रिसाव शुरू करने का जोखिम उठाते हैं।

सर्वोत्तम अभ्यास: निर्देशों को स्वयं के बाद साफ करना चाहिए। आप तत्व को हटा सकते हैं। ('$ नष्ट', ...) या गुंजाइश। निर्देश को हटाए जाने पर एक क्लीन-अप फ़ंक्शन को चलाने के लिए $ ('$ नष्ट', ...) पर।

सवाल:

मेरे element.on "click", (event) ->अंदर मेरा निर्देश है:

  1. जब निर्देश को नष्ट कर दिया जाता है, तो क्या element.onइसे संग्रहित किए जाने वाले कचरे से रखने के लिए कोई मेमोरी संदर्भ हैं ?
  2. कोणीय प्रलेखन में कहा गया है कि मुझे $destroyउत्सर्जित घटना पर श्रोताओं को हटाने के लिए हैंडलर का उपयोग करना चाहिए । मैं इस धारणा के तहत था कि destroy()इवेंट श्रोताओं को हटा दिया जाए, क्या यह मामला नहीं है?

जवाबों:


433

घटना सुनने वाले

सबसे पहले यह समझना महत्वपूर्ण है कि "ईवेंट श्रोता" दो प्रकार के हैं:

  1. स्कोप इवेंट श्रोताओं के माध्यम से पंजीकृत $on:

    $scope.$on('anEvent', function (event, data) {
      ...
    });
    
  2. उदाहरण के लिए onया इसके माध्यम से तत्वों से जुड़े इवेंट हैंडलर bind:

    element.on('click', function (event) {
      ...
    });
    

$ गुंजाइश। $ नष्ट ()

जब $scope.$destroy()इसे निष्पादित किया जाता है तो यह $onउस $ स्कोप पर पंजीकृत सभी श्रोताओं को हटा देगा ।

यह DOM तत्वों या दूसरी तरह के किसी अटैच इवेंट हैंडलर को नहीं हटाएगा।

इसका मतलब यह है कि $scope.$destroy()निर्देश के लिंक फ़ंक्शन के भीतर उदाहरण से मैन्युअल रूप से कॉल करने से उदाहरण के लिए संलग्न हैंडलर नहीं हटाया जाएगा element.on, न ही DOM तत्व।


element.remove ()

ध्यान दें कि removeएक jqLite विधि (या jQuery विधि यदि jQuery को AngularjS से पहले लोड किया गया है) और मानक DOM तत्व ऑब्जेक्ट पर उपलब्ध नहीं है।

जब element.remove()उस तत्व को निष्पादित किया जाता है और उसके सभी बच्चों को एक साथ डोम से हटा दिया जाएगा, तो सभी घटना संचालकों को उदाहरण के लिए संलग्न किया जाएगा element.on

यह तत्व से जुड़े $ स्कोप को नष्ट नहीं करेगा ।

इसे और अधिक भ्रमित करने के लिए एक jQuery इवेंट भी कहा जाता है $destroy। कभी-कभी तत्वों को हटाने वाले तृतीय-पक्ष jQuery पुस्तकालयों के साथ काम करते समय, या यदि आप उन्हें मैन्युअल रूप से हटाते हैं, तो आपको उस पर सफाई करने की आवश्यकता हो सकती है:

element.on('$destroy', function () {
  scope.$destroy();
});

जब एक निर्देश "नष्ट" हो जाए तो क्या करें

यह इस बात पर निर्भर करता है कि निर्देश "नष्ट" कैसे हुआ है।

एक सामान्य मामला यह है कि एक निर्देश नष्ट हो जाता है क्योंकि ng-viewवर्तमान दृश्य बदल जाता है। जब ऐसा होता है तो ng-viewनिर्देश संबंधित $ स्कोप को नष्ट कर देगा, सभी संदर्भों को उसके मूल स्कोप से अलग कर देगा और remove()तत्व को कॉल करेगा।

इसका मतलब यह है कि अगर यह दृश्य इसके लिंक फ़ंक्शन में इसके साथ एक निर्देश सम्‍मिलित करता है जब यह इसके द्वारा नष्ट हो जाता है ng-view:

scope.$on('anEvent', function () {
 ...
});

element.on('click', function () {
 ...
});

दोनों घटना श्रोताओं को स्वचालित रूप से हटा दिया जाएगा।

हालांकि, यह ध्यान रखना महत्वपूर्ण है कि इन श्रोताओं के अंदर का कोड अभी भी मेमोरी लीक का कारण बन सकता है, उदाहरण के लिए यदि आपने सामान्य जेएस मेमोरी लीक पैटर्न प्राप्त किया है circular references

यहां तक ​​कि एक निर्देश के इस सामान्य मामले में एक दृश्य बदलने के कारण नष्ट हो रहा है, ऐसी चीजें हैं जिन्हें आपको मैन्युअल रूप से साफ करने की आवश्यकता हो सकती है।

उदाहरण के लिए यदि आपने एक श्रोता को पंजीकृत किया है $rootScope:

var unregisterFn = $rootScope.$on('anEvent', function () {});

scope.$on('$destroy', unregisterFn);

यह जरूरत है क्योंकि $rootScopeआवेदन के जीवनकाल के दौरान कभी नष्ट नहीं होता है।

यदि आप किसी अन्य पब / उप कार्यान्वयन का उपयोग कर रहे हैं, तो यह तब होता है जब $ स्कोप नष्ट हो जाने पर, या यदि आपका निर्देश सेवाओं के लिए कॉलबैक से गुजरता है, तो अपने आप आवश्यक क्लीनअप नहीं करता है।

एक अन्य स्थिति रद्द करने के लिए किया जाएगा $interval/ $timeout:

var promise = $interval(function () {}, 1000);

scope.$on('$destroy', function () {
  $interval.cancel(promise);
});

यदि आपका निर्देश ईवेंट हैंडलर को वर्तमान दृश्य के बाहर के तत्वों के लिए संलग्न करता है, तो आपको उन लोगों को भी मैन्युअल रूप से साफ़ करने की आवश्यकता है:

var windowClick = function () {
   ...
};

angular.element(window).on('click', windowClick);

scope.$on('$destroy', function () {
  angular.element(window).off('click', windowClick);
});

ये कुछ उदाहरण थे कि जब कोणीय द्वारा निर्देशों को "नष्ट" किया जाता है, तो उदाहरण के लिए ng-viewया ng-if

यदि आपके पास कस्टम निर्देश हैं जो DOM तत्वों आदि के जीवनचक्र का प्रबंधन करते हैं, तो यह निश्चित रूप से अधिक जटिल हो जाएगा।


4
'$ rootScope एप्लिकेशन के जीवनकाल के दौरान कभी नष्ट नहीं होता है।' : स्पष्ट रूप से एक बार जब आप इसके बारे में सोचते हैं। यही मुझे याद आ रहा था।
user276648

@tasseKATT यहाँ एक छोटा सा प्रश्न है, यदि एक ही नियंत्रक में हमारे पास कई $ rootScope है। अलग-अलग घटनाओं के लिए $।, तो क्या हम $ गुंजाइश कहेंगे। $ पर ("$ नष्ट", ListenerName1); प्रत्येक $ rootScope के लिए। $ अलग तरीके से ??
यशिका गर्ग '

2
@YashikaGarg यह संभवत: सिर्फ एक सहायक समारोह होगा जो सभी श्रोताओं को बुलाएगा। $ गुंजाइश की तरह। $ ('$ नष्ट'), फ़ंक्शन () {ListenerName1 (); ListenerName2 (); ...}); क्या गैर-पृथक स्कोप पर घटना संचालकों पर $ के लिए कोई अतिरिक्त जटिलता है? या दो तरह से बाइंडिंग के साथ स्कोप्स को अलग करें?
डेविड राइस

$ Rootcope पर इवेंट श्रोताओं को क्यों पंजीकृत करें? मैं घटना श्रोताओं को $ स्कोप पर पंजीकृत करता हूं और फिर अन्य नियंत्रक $ rootcope.broadcast ('Eventname') का प्रदर्शन करते हैं और मेरे ईवेंट श्रोता चलते हैं। क्या ये ईवेंट श्रोता $ स्कोप पर हैं जो एप्लिकेशन ईवेंट को सुन रहे हैं जो अभी भी ऑटो से साफ हो रहे हैं?
स्काइचन

@Skychan क्षमा करें, मैं आपकी टिप्पणी से चूक गया। यह एक अनुमान है, लेकिन लोग इसके $rootScopeकारण उपयोग कर सकते हैं : stackoverflow.com/questions/11252780/… ध्यान दें कि जैसा कि उत्तर में शीर्ष पर है, इसे बदल दिया गया है। हां, $scopeजब उस स्कोप को नष्ट कर दिया जाता है , तो सामान्य पर ईवेंट श्रोताओं को ऑटो से साफ किया जाएगा।
tasseKATT
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.