2012-02-16 14 views
14

मुझे लगता है कि .on() के माध्यम से पंजीकृत ईवेंट हैंडलर $.cache में आयोजित किए गए हैं। मैं यह भी देखता हूं कि ईवेंट हैंडलर $(elem).data() में भी आयोजित किए जाते हैं।

वस्तुओं $.cache में आयोजित डोम नोड्स, जिन पर ईवेंट पंजीकृत हैं देखें। जब डीओएम नोड्स अलग हो जाते हैं, तो यह स्मृति रिसाव की ओर जाता है, और इससे .off() कॉल अनिवार्य है।

मैं एक स्थिति है जब डोम नोड (जो करने के लिए मैं ईवेंट हैंडलर संलग्न) अलग किया जा रहा है, जहां मैं नहीं जानता है। जबकि मैं अपने कोड में उस डोम नोड का संदर्भ रख सकता हूं और साफ़ करने के लिए .off() पर कॉल कर सकता हूं, यह अच्छा प्रतीत नहीं होता है, क्योंकि यह पता नहीं है कि डोम नोड को हटाया जा रहा है।

ऐसा करने का सबसे अच्छा तरीका क्या है?

उत्तर

16

"ऐसा करने का सबसे अच्छा तरीका क्या है?"

आप jQuery का उपयोग करने के लिए जा रहे हैं, तो आप अपनी API तत्वों को दूर करने के लिए उपयोग करना चाहिए, और आप उचित तरीकों का उपयोग आवश्यक है, अन्यथा, जैसा कि आप ने कहा, आप मेमोरी लीक होगा।

यदि आप जब डोम नोड हटाया जा रहा है पता नहीं है, और अगर यह एक रिसाव खड़ी कर रहा है, मुझे लगता है कि हम इस का मतलब है कि आप jQuery के साथ-साथ एक और पुस्तकालय का उपयोग कर रहे हैं। इस कारण से यह सिर्फ एक अच्छा विचार नहीं है।

आपको यह सुनिश्चित करने की आवश्यकता है कि jQuery द्वारा प्रभावित किसी भी तत्व को jQuery द्वारा हटा दिया गया है। $.cache में संग्रहीत कुछ डेटा भी है जिसे आपने स्पष्ट रूप से सेट नहीं किया था। इसका मतलब यह है कि सभी तत्वों को jQuery के साथ हटाया जाना चाहिए, केवल सोचें कि डेटा हो सकता है।


"jQuery में $.cache का उद्देश्य क्या है?"

हैंडलर और तत्वों के साथ अन्य डेटा को जोड़ने के लिए। डेटा और तत्वों के बीच का लिंक मूल रूप से तत्व पर विस्तारित संपत्ति पर संग्रहीत एक धारावाहिक संख्या है।

आप jQuery के बिना तत्व निकाल देते हैं, $.cache में संबद्ध डेटा अनाथ है।

संभावित दृष्टिकोण को रोकने के लिए इस दृष्टिकोण का उद्देश्य था। दुर्भाग्य से यह संभावित रूप से अधिक गंभीर रिसाव बनाता है।

+0

1. तत्व और संचालकों के बीच संबंध एक सीरियल नंबर के माध्यम से बनाए रखा है (और हैंडलर तत्व की बात नहीं कर रहा है), मैं एक कारण है कि .cache प्रविष्टियों स्मृति के लिए नेतृत्व चाहिए नहीं दिख रहा है रिसाव। किसी कारण से, मुझे नहीं पता कि यह कितना न्यायसंगत है, कैश प्रविष्टि तत्व का जिक्र कर रही है। मुझे यह जानकर उत्सुकता है कि तत्व का संदर्भ क्यों आवश्यक है। 2. मुझे उन मामलों के बारे में पता नहीं है जिनमें तत्व का विस्तार करने से ऑब्जेक्ट्स (हैंडलर) के संदर्भ सीधे नहीं हो सकते हैं। यदि विस्तारक संदर्भ धारण कर सकता है, तो मुझे संदर्भों को पकड़ने के लिए समानांतर संरचना की आवश्यकता नहीं है। – user968903

+0

@ user968903: 1. यदि आप jQuery को हटाने के दौरान संबंधित '$ .cache' प्रविष्टि को हटाते हैं तो आप केवल लीक का नेतृत्व करते हैं। सीरियल नंबर दोनों के बीच एकमात्र कनेक्शन है, इसलिए यदि सीरियल '123' वाला तत्व हटा दिया गया है, लेकिन jQuery '$ .cache' में प्रविष्टि' 123' को नहीं हटाता है, तो वह प्रविष्टि अब डेटा का जिक्र कर रही है जो अब नहीं एक समान तत्व है, और कभी साफ नहीं किया जाएगा। औचित्य संभावित मेमोरी लीक था जो मुख्य रूप से आईई 6 और शायद आईई 7 में मौजूद था। अब जब वे ब्राउज़र लगभग चले गए हैं, मुझे नहीं पता कि यह दृष्टिकोण अच्छा है या नहीं। –

+0

@ user968903: 2. मुझे लगता है कि आधुनिक ब्राउज़र आमतौर पर निकाले जाने पर तत्वों को साफ़ करते हैं, इसलिए शायद यह अब तक कोई समस्या नहीं है। मेरा मानना ​​है कि यह मुख्य रूप से आईई 6/7 था जिसमें मुद्दों थे। मुझे लगता है कि बंद होने के संबंध में अभी भी संभावित मेमोरी लीक हो सकती हैं, जहां एक तत्व के पास एक हैंडलर होता है जो इसके परिवर्तनीय दायरे में एक परिपत्र संदर्भ होता है, लेकिन मुझे यकीन नहीं है कि यह आज कोई मुद्दा है या नहीं। मैं देखूंगा कि मुझे क्या मिल सकता है। –

5

मैं एक ऐसी ही स्थिति है जहाँ नॉकआउट दस्तावेज़ से जोड़ सकते हैं और डोम पेड़ को हटाने के लिए प्रयोग किया जाता है करने के लिए भाग गया। हालांकि, इवेंट श्रोताओं को इन डोम पेड़ों में संलग्न करने के लिए jquery का उपयोग किया जाता है। जब नॉकआउट दस्तावेज़ से डोम तत्वों को हटा देता है तो श्रोताओं को अनबाउंड नहीं होता है, इसलिए डोम पेड़ कभी कचरा संग्रह के लिए योग्य नहीं होता है। हमने एक क्लीन अप फ़ंक्शन जोड़ा है जो हर बार हैश में $ jcery $ .cache के माध्यम से चलता है और दस्तावेज़ में नहीं होने वाले डोम पेड़ से बंधे हैंडलर भी पाता है। इसके बाद श्रोताओं को कचरा संग्रह के लिए योग्य डोम पेड़ बनाने और अधिकांश लीक को ठीक करने के लिए हम देख रहे हैं, जिसे हम 13 एमबी रिसाव के लिए इस्तेमाल किए गए ऐप के चारों ओर गोल यात्रा करते हैं, अब यह जगहों में इन बदलावों के साथ केवल 3 एमबी लीक है।

for (var i in $.cache) { 
      if ($.cache.hasOwnProperty(i)) { 

       if ($.cache[i].handle && $.cache[i].handle.elem && document !== $.cache[i].handle.elem && !jQuery.contains(document, $.cache[i].handle.elem)) { 
        //we have an event handler pointing to a detached dom element! 
        //this is a memory leak as this detached dom element cannot be garbage collected until 
        //all references to it are removed. So lets delete the event handler to get memory back! 
        var orphan = $($.cache[i].handle.elem); 
        $('body').append(orphan); 
        orphan.off(); 
        orphan.remove(); 
        orphan = null; 
       } 
      } 
     } 
+1

ऐसा लगता है कि यह नॉकआउट 3.0.0 में एक बग का परिणाम है, जब मैंने 3.1.0 में अपग्रेड किया था तो मेमोरी लीक उपरोक्त कोड की आवश्यकता के बिना चली गई! – Troup

संबंधित मुद्दे