मैप इंस्टेंस को नष्ट करने का उचित तरीका क्या है?


89

मैंने हाल ही में एक HTML5 मोबाइल एप्लिकेशन विकसित किया है। आवेदन एक एकल पृष्ठ था जहां नेविगेशन हैश परिवर्तन घटनाओं ने पूरे डोम को बदल दिया। एप्लिकेशन का एक खंड API v3 का उपयोग करके Google मानचित्र था। इससे पहले कि मैप div को DOM से हटा दिया जाए, मैं किसी भी इवेंट हैंडलर / श्रोताओं को हटाना चाहता हूं और जितना संभव हो उतना मेमोरी खाली कर सकता है क्योंकि उपयोगकर्ता फिर से उस सेक्शन में वापस नहीं आ सकता है।

मानचित्र उदाहरण को नष्ट करने का सबसे अच्छा तरीका क्या है?


संबंधित प्रश्न (2014): stackoverflow.com/questions/21142483/…
kashiraja

मानचित्र पर सभी ईवेंट श्रोताओं को निकालने का प्रयास करने के लिए कोड, Google बग 35821412
kashiraja

जवाबों:


48

मैं इस प्रश्न पर एक दूसरा उत्तर जोड़ रहा हूं, क्योंकि मैं अपने पिछले उत्तर पर अनुवर्ती टिप्पणियों के माध्यम से आगे और पीछे नहीं हटना चाहता।

लेकिन मुझे हाल ही में कुछ ऐसी जानकारी मिली है जो सीधे आपके सवाल का जवाब देती है और इसलिए मैं साझा करना चाहता हूं। मुझे नहीं पता कि आप इसके बारे में जानते हैं, लेकिन Google मैप्स एपीआई ऑफिस आवर्स 9 मई 2012 वीडियो के दौरान, Google से क्रिस ब्रॉडफुट और ल्यूक माहे ने स्टैकओवरफ्लो से इस बहुत ही सवाल पर चर्चा की । यदि आप वीडियो प्लेबैक को 12:50 पर सेट करते हैं, तो यह वह खंड है जहां वे आपके प्रश्न पर चर्चा करते हैं।

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

किसी भी दर पर, बस इसे पास करना चाहते थे और यह सुनिश्चित करना चाहते थे कि यह स्टैक्वेरफ्लो चर्चा में शामिल हो और आशा है कि यह आपकी और दूसरों की मदद करता है-


2
धन्यवाद - मैंने उनसे कार्यालय के समय पर प्रश्न से निपटने के लिए कहा, लेकिन अभी तक वीडियो की जांच करने का मौका नहीं मिला।
चाड किलिंग्सवर्थ

खैर आप बस पिछले जवाब का उल्लेख कर सकते हैं कि यह एक अद्यतन है ...
TJ

4
अच्छा कमाल .. यह 2018 है और अभी भी ऐसा करने का कोई तरीका नहीं है।
जेपी सिल्वाशी

28

आधिकारिक जवाब तुम नहीं है। एक ही पृष्ठ के अनुप्रयोग में मानचित्र उदाहरणों का पुन: उपयोग किया जाना चाहिए और फिर नष्ट नहीं किया जाना चाहिए।

कुछ एकल पृष्ठ अनुप्रयोगों के लिए, इसका मतलब यह हो सकता है कि समाधान को फिर से तैयार करना जैसे कि एक बार नक्शा बनाने के बाद इसे DOM से छिपाया या डिस्कनेक्ट किया जा सकता है, लेकिन यह कभी नष्ट नहीं होता / फिर से बनाया जाता है।


यह बहुत बुरा है - मेरे पास बहुभाषी एकल पृष्ठ अनुप्रयोग है और मैं चयनित भाषा पर Google मानचित्र प्रदर्शित करना चाहता हूं।
Artuska

14

चूंकि जाहिरा तौर पर आप नक्शे के उदाहरणों को नष्ट नहीं कर सकते हैं, इस समस्या को कम करने का एक तरीका यदि

  • आपको एक वेबसाइट पर एक साथ कई मानचित्र दिखाने की आवश्यकता है
  • उपयोगकर्ता इंटरैक्शन के साथ नक्शे की संख्या बदल सकती है
  • मानचित्रों को अन्य घटकों के साथ छिपाया और फिर से दिखाया जाना चाहिए (अर्थात वे DOM में एक निश्चित स्थिति में नहीं दिखाई देते हैं)

नक्शे के उदाहरणों का एक पूल रख रहा है। पूल उपयोग किए जा रहे उदाहरणों का ट्रैक रखता है, और जब यह एक नया उदाहरण का अनुरोध किया जाता है, तो यह जांचता है कि क्या उपलब्ध नक्शे में से कोई भी स्वतंत्र है: यदि यह है, तो यह एक मौजूदा एक लौटा देगा, यदि यह नहीं है, तो यह एक निर्माण करेगा नया नक्शा उदाहरण और इसे लौटाकर, इसे पूल में जोड़कर। इस तरह आपके पास केवल एक ही बार में स्क्रीन पर एक साथ दिखाए जाने वाले अधिकतम मैप्स के बराबर अधिकतम संख्याएँ होंगी। मैं इस कोड का उपयोग कर रहा हूं (इसके लिए jQuery की आवश्यकता है):

var mapInstancesPool = {
 pool: [],
 used: 0,
 getInstance: function(options){
    if(mapInstancesPool.used >= mapInstancesPool.pool.length){
        mapInstancesPool.used++;
        mapInstancesPool.pool.push (mapInstancesPool.createNewInstance(options));
    } else { 
        mapInstancesPool.used++;
    }
    return mapInstancesPool.pool[mapInstancesPool.used-1];
 },
 reset: function(){
    mapInstancesPool.used = 0;
 },
 createNewInstance: function(options){
    var div = $("<div></div>").addClass("myDivClassHereForStyling");
    var map =   new google.maps.Map(div[0], options);
    return {
        map: map,
        div: div
    }
 }
}

आप इसे प्रारंभिक मानचित्र विकल्प (जैसे google.maps.ap के निर्माता के दूसरे तर्क के अनुसार) पास करते हैं, और यह दोनों नक्शा उदाहरण देता है (जिस पर आप google.maps.Map से संबंधित कार्य कह सकते हैं), और कंटेनर, जो आप "myDivClassHereForStyling" क्लास का उपयोग करके स्टाइल कर सकते हैं, और आप DOM करने के लिए व्यावहारिक रूप से अपील कर सकते हैं। यदि आपको सिस्टम रीसेट करने की आवश्यकता है, तो आप mapInstancesPool.reset () का उपयोग कर सकते हैं। यह पुन: उपयोग के लिए पूल में सभी मौजूदा उदाहरणों को रखते हुए काउंटर को 0 पर रीसेट कर देगा। मेरे आवेदन में मुझे एक ही बार में सभी मानचित्रों को हटाने और मानचित्रों का एक नया सेट बनाने की आवश्यकता थी, इसलिए किसी विशिष्ट मानचित्र उदाहरण को रीसायकल करने का कोई कार्य नहीं है: आपका माइलेज भिन्न हो सकता है। नक्शे को स्क्रीन से हटाने के लिए, मैं jQuery की टुकड़ी का उपयोग करता हूं, जो मानचित्र के कंटेनर को नष्ट नहीं करता है।

इस प्रणाली का उपयोग करके, और उपयोग करके

google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);

और चल रहा है

google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()

(जहाँ divReference है डिव का jQuery ऑब्जेक्ट इंस्टेंस पूल से लौटाया जाता है) हर उस डिव पर, जिसे मैं हटा रहा हूँ, मैं क्रोम की मेमोरी के उपयोग को कम या ज्यादा स्थिर रखने में कामयाब रहा, क्योंकि हर बार जब मैं नक्शे हटाता हूं और नए जोड़ता हूं तो इसका विरोध होता है।


तुम मेरे जीवन को बचा लिया है! थंक्स;)
फेलिप डेसिडेराटी जूल

सहायता करके हमें खुशी होगी!!
पाओलो मिओनी

5

मैंने मानचित्र div की सामग्री को हटाने का सुझाव दिया होगा और deleteचर का उपयोग करते हुए मानचित्र के संदर्भ को पकड़ेगा, और संभवत: deleteकिसी भी घटना के श्रोताओं को स्पष्ट रूप से प्रभावित करेगा।

नहीं है एक स्वीकृत बग , हालांकि, और यह काम नहीं हो सकता।


यह एक अच्छी चर्चा है। मुझे नहीं लगता कि कॉलिंग deleteबहुत कुछ जोड़ता है (देखें stackoverflow.com/q/742623/1314132 ), लेकिन यह वास्तव में चोट नहीं पहुंचा सकता है। अंत में, यह इस सवाल पर आता है: क्या वस्तु का कोई संदर्भ है? यदि हाँ, तो यह कचरा एकत्र नहीं किया जाएगा।
सीन मिकी

1
@ सीनमिकी: वह जगह है जहाँ बग प्रासंगिक हो जाता है। संस्करण 2 में GUnload()एपीआई के सभी आंतरिक संदर्भों को हटाना है।
एंड्रयू लीच

मैं Chrome में इस पृष्ठ के साथ परीक्षण कर रहा हूं: People.missouristate.edu/chadkillingsworth/mapsexamples/…। अब तक मानचित्र हटाए जाने के बाद मेमोरी का उपयोग केवल थोड़ा कम हो जाता है, लेकिन मानचित्र के त्वरित होने से पहले के स्तर के पास कहीं नहीं है।
चाड किलिंग्सवर्थ

@AndrewLeach बिल्कुल। लेकिन अगर उनके पास एक बग है जो स्मृति रिसाव का कारण बन रहा है, तो बहुत कुछ नहीं है जो हम तय होने तक कर सकते हैं। मेरा मतलब है, अगर सभी मैप ऑब्जेक्ट्स को अप्राप्य बनाने से काम नहीं चलता है, तो deleteवास्तव में यह ठीक नहीं है। उन्हें बड़े को ठीक करना होगा ताकि संदर्भों को अनुपयोगी बना दिया जाए क्योंकि यह एक नया फ़ंक्शन जोड़ना चाहिए या आपके द्वारा वर्णित कार्यक्षमता प्रदान करता है GUnload()
सीन मिकी

1
चाड / एंड्रयू: हाँ, मैंने इस मुद्दे को पुन: पेश किया है, दुर्भाग्य से deleteऔर innerHTMLपूरी तरह से स्पष्ट स्मृति को साफ नहीं करता है। दुर्भाग्य से यह एक उच्च प्राथमिकता बग नहीं है।
क्रिस ब्रॉडफुट

2

जैसा कि google doesn't को html में api v3 बेहतर उपयोग iframe के लिए गनलोड () प्रदान करता है और इस ifame के स्रोत के रूप में map.html असाइन करता है। उपयोग के बाद src को null बना दें। यह निश्चित रूप से मानचित्र द्वारा खपत की गई मेमोरी को मुक्त करेगा।


2
Iframe के प्रत्येक उदाहरण को फिर से उन मानचित्रों को पुनः लोड करना होगा जो आदर्श नहीं हैं।
चाड किलिंग्सवर्थ

1

जब आप इसे हटाते हैं div, तो यह डिस्प्ले पैनल को हटा देता है और नक्शा गायब हो जाएगा। मानचित्र का उदाहरण निकालने के लिए, बस यह सुनिश्चित कर लें कि मानचित्र के लिए आपका संदर्भ सेट है nullऔर नक्शे के अन्य भागों के लिए कोई संदर्भ सेट किया गया है null। उस समय, जावास्क्रिप्ट कचरा संग्रहण सफाई का ध्यान रखेगा, जैसा कि इसमें वर्णित है: जावास्क्रिप्ट संग्रह कचरा कैसे काम करता है?


1
मुझे यकीन नहीं है कि मानचित्र चर को अशक्त करने के लिए सभी घटना श्रोताओं को ठीक से हटा दिया जाएगा।
चाड किलिंग्सवर्थ

1
यह न सिर्फ नक्शा है null, जिसे सेट करना है , बल्कि किसी भी चीज का संदर्भ है। इसलिए यदि मार्कर संदर्भ सेट हो जाता है null, तो यह पहुंच से बाहर हो जाता है, तो ईवेंट श्रोता तक पहुंचने का कोई रास्ता नहीं है। यह अभी भी मानचित्र से जुड़ा हो सकता है, लेकिन मानचित्र तक नहीं पहुंचा जा सकता है, इसलिए यह सिर्फ स्मृति का एक बड़ा हिस्सा है जो अनिवार्य रूप से अनाथ हो गया है। यह एक सेटिंग के रूप में ही है Array.length = 0; यदि सदस्यों के लिए कोई अन्य संदर्भ नहीं है, तो वे केवल अनाथ स्मृति का एक समूह बनाते हैं जो कचरा संग्रहण के लिए योग्य है।
सीन मिकी

0

मुझे लगता है कि आप बात कर रहे हैं addEventListener। जब आप DOM तत्वों को हटाते हैं, तो कुछ ब्राउज़र इन घटनाओं को लीक करते हैं और उन्हें हटाते नहीं हैं। यही कारण है कि jQuery एक तत्व को हटाते समय कई काम करता है:

  • यह उन घटनाओं को हटा देता है जब यह उपयोग कर सकता है removeEventListener। इसका मतलब है कि यह इस श्रोता को इस तत्व पर जोड़े गए इवेंट श्रोताओं के साथ एक सरणी रख रहा है।
  • यह उपलब्ध नहीं होने पर DOM तत्व का उपयोग करके घटनाओं ( onclick,, onblurआदि) के बारे में विशेषताओं को हटा देता है (फिर भी, इसमें एक सरणी होती है जहां यह जोड़े गए घटनाओं को संग्रहीत करता है)।deleteaddEventListener
  • यह nullIE 6/7/8 मेमोरी लीक से बचने के लिए तत्व सेट करता है ।
  • यह तब तत्व को हटा देता है।

मैं मुख्य रूप से आंतरिक Google मैप्स एपीआई घटनाओं की बात कर रहा हूं। उन्हें डेवलपर्स इवेंट में प्रलेखित एपीआई इवेंट विधियों का उपयोग करके जोड़ा / हटाया / ट्रिगर किया जा सकता है । जबकि ब्राउज़र addEventListener की कार्यक्षमता में समान है, नक्शे के लिए विशिष्ट कस्टम इवेंट्स की एक बड़ी संख्या है (जैसे कि "bounds_changed" और उनमें से कुछ इवेंट हैंडलर ब्राउज़र इवेंट्स में हुक करते हैं जैसे कि मैप "resize" इवेंट
चाड किलिंग्सवर्थ

फिर जोड़े गए ईवेंट्स की एक सरणी रखें और उस तरह के ईवेंट के आधार पर मैन्युअल रूप से उपयोग करके removeEventListenerया हटा दें delete
फ्लोरियन मार्गाइन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.