맵 인스턴스를 삭제하는 올바른 방법은 무엇입니까?


90

최근에 html5 모바일 애플리케이션을 개발했습니다. 애플리케이션은 탐색 해시 변경 이벤트가 전체 DOM을 대체하는 단일 페이지였습니다. 애플리케이션의 한 섹션은 API v3를 사용하는 Google지도였습니다. 맵 div가 DOM에서 제거되기 전에 이벤트 핸들러 / 리스너를 제거하고 사용자가 해당 섹션으로 다시 돌아갈 수없는 한 가능한 한 많은 메모리를 확보하고 싶습니다.

맵 인스턴스를 파괴하는 가장 좋은 방법은 무엇입니까?



코드는지도에있는 모든 이벤트 리스너를 제거하기 위해, 구글은 버그 매핑 35821412
kashiraja

답변:


49

이 질문에 대한 두 번째 답변을 추가하고 있습니다. 이전 답변에 대한 후속 의견을 통해 앞뒤로 가졌던 내용을 제거하고 싶지 않기 때문입니다.

하지만 최근에 귀하의 질문을 직접적으로 다루는 몇 가지 정보를 발견했기 때문에 공유하고 싶었습니다. 이 사실을 알고 있는지는 모르겠지만 Google Maps API Office Hours 2012 년 5 월 9 일 비디오 에서 Google의 Chris Broadfoot과 Luke Mahe 는 stackoverflow 에서이 질문에 대해 논의 했습니다 . 비디오 재생을 12:50으로 설정하면이 섹션에서 질문에 대해 논의합니다.

본질적으로 그들은 그것이 버그임을 인정하지만, 연속적인 맵 인스턴스를 생성 / 파괴하는 것과 관련된 사용 사례를 실제로 지원하지 않는다고 덧붙입니다. 지도의 단일 인스턴스를 만들고 이러한 종류의 모든 시나리오에서 재사용 할 것을 강력히 권장합니다. 또한지도를 null로 설정하고 이벤트 리스너를 명시 적으로 제거하는 방법에 대해서도 설명합니다. 이벤트 리스너에 대한 우려를 표명하고 맵을 null로 설정하는 것으로 충분하다고 생각했지만 이벤트 리스너를 구체적으로 언급하기 때문에 우려 사항이 유효한 것 같습니다. 그들은 또한지도를 보유하는 DIV도 완전히 제거 할 것을 권장했습니다.

어쨌든, 이것을 전달하고 그것이 stackoverflow 토론에 포함되어 있는지 확인하고 당신과 다른 사람들에게 도움이되기를 바랍니다.


2
감사합니다. 근무 시간에 질문에 답해달라고 요청했지만 아직 동영상을 확인할 기회가 없었습니다.
Chad Killingsworth

글쎄요 당신은 단순히 업데이트라고 언급하는 이전 답변을 업데이트 할 수 있습니다 ...
TJ

4
굉장하네요 .. 2018 년이었는데 아직 방법이없는 것 같습니다.
JP Silvashy

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.Map 생성자의 두 번째 인수에 따라)을 전달하고지도 인스턴스 (google.maps.Map과 관련된 함수를 호출 할 수있는)와 컨테이너를 모두 반환합니다. "myDivClassHereForStyling"클래스를 사용하여 스타일을 지정할 수 있으며 DOM에 동적으로 추가 할 수 있습니다. 시스템을 재설정해야하는 경우 mapInstancesPool.reset ()을 사용할 수 있습니다. 재사용을 위해 풀의 모든 기존 인스턴스를 유지하면서 카운터를 0으로 재설정합니다. 내 응용 프로그램에서 한 번에 모든지도를 제거하고 새지도 집합을 만들어야했기 때문에 특정지도 인스턴스를 재활용하는 기능이 없습니다. 마일리지가 다를 수 있습니다. 화면에서지도를 제거하려면지도의 컨테이너를 파괴하지 않는 jQuery의 detach를 사용합니다.

이 시스템을 사용하고

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

그리고 달리기

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

(여기서 divReference는 인스턴스 풀에서 반환 된 div의 jQuery 객체입니다) 제거하는 모든 div에서 Chrome의 메모리 사용량을 어느 정도 안정적으로 유지할 수 있었는데,지도를 삭제하고 새지도를 추가 할 때마다 증가하는 것과는 대조적이었습니다.


당신은 내 생명을 구했습니다! Thnks;)
Felipe Desiderati

도움이되어 기쁩니다 !!
Paolo Mioni

5

지도 div의 내용을 제거하고지도 delete에 대한 참조를 포함하는 변수를 사용 하고 아마도 delete모든 이벤트 리스너를 명시 적으로 지정 하는 것이 좋습니다.

인정받는 버그는 하지만,이 작동하지 않을 수 있습니다.


이것은 좋은 토론입니다. 나는 전화 delete가 많은 것을 추가 한다고 생각하지 않지만 ( stackoverflow.com/q/742623/1314132 참조 ) 정말 아프지는 않습니다. 결국이 질문으로 귀결됩니다. 객체에 대한 참조가 있습니까? 그렇다면 가비지 수집되지 않습니다.
Sean Mickey

1
@SeanMickey : 버그가 관련되는 곳입니다. 버전 2는 GUnload()모든 API의 내부 참조를 제거해야합니다.
Andrew Leach

Chrome에서이 페이지를 테스트했습니다. people.missouristate.edu/chadkillingsworth/mapsexamples/… 지금까지지도가 제거 된 후 메모리 사용량은 약간만 떨어지지 만지 도가 인스턴스화되기 전의 수준 근처에는 없습니다.
Chad Killingsworth

@AndrewLeach 물론입니다. 그러나 메모리 누수를 일으키는 버그가있는 경우 수정 될 때까지 할 수있는 일이별로 없습니다. 내 말은, 모든지도 객체를 접근 할 수 없게 만드는 것이 작동 delete하지 않는다면 실제로 수정이되지는 않습니다. 참조에 도달 할 수 없게 작동하도록 큰 문제를 수정하거나 설명하는 기능을 제공하는 새 기능을 추가해야합니다 GUnload().
Sean Mickey

1
차드 / 앤드류 : 그래, 나는 불행하게도이 문제를 재현 delete하고, 삭제 innerHTML하지 않습니다 완전히 명확한 메모리를. 불행히도 이것은 우선 순위가 높은 버그가 아닙니다.
Chris Broadfoot

2

Google은 api v3에 gunload ()를 제공하지 않으므로 html에서 iframe을 더 잘 사용하고이 iframe에 대한 소스로 map.html을 할당합니다. 사용 후 src를 null로 만드십시오. 그것은 확실히 맵이 소비하는 메모리를 해제 할 것입니다.


2
그런 다음 iframe의 각 인스턴스는 이상적이지 않은지도 API를 다시로드해야합니다.
Chad Killingsworth 2013-08-24

1

당신이를 제거하면 div, 그 디스플레이 패널을 제거하고지도가 사라집니다. 지도 인스턴스를 제거하려면지도에 대한 참조가로 설정되어 null있고지도의 다른 부분에 대한 모든 참조 가로 설정되어 있는지 확인하십시오 null. 이 시점에서 JavaScript 가비지 콜렉션은 다음에서 설명한대로 정리를 처리합니다. 가비지 콜렉션은 JavaScript에서 어떻게 작동합니까? .


1
지도 변수를 null로 설정하면 모든 이벤트 리스너가 제대로 제거되는지 잘 모르겠습니다.
Chad Killingsworth

1
로 설정 null해야하는지도뿐만 아니라 다른 항목에 대한 참조입니다. 마커 참조로 설정한다면 null그것은 만들기, 도달 할 수없는 , 이벤트 리스너에 도달 할 수있는 방법은 없습니다. 여전히지도에 연결되어있을 수 있지만지도에 도달 할 수 없으므로 본질적으로 고아가 된 큰 메모리 덩어리입니다. 설정과 동일합니다 Array.length = 0. 멤버에 대한 다른 참조가 없으면 가비지 콜렉션에 적합한 고아 메모리 그룹을 형성합니다.
Sean Mickey

0

에 대해 말하는 것 같아요 addEventListener. DOM 요소를 제거 할 때 일부 브라우저는 이러한 이벤트를 유출하고 제거하지 않습니다. 이것이 요소를 제거 할 때 jQuery가 여러 가지 작업을 수행하는 이유입니다.

  • 사용할 수있는 경우 이벤트를 제거합니다 removeEventListener. 즉,이 요소에 추가 한 이벤트 리스너와 함께 배열을 유지합니다.
  • 사용할 수없는 경우 DOM 요소를 사용하여 이벤트 ( onclick, onblur등) 에 대한 속성을 삭제합니다 (여전히 추가 된 이벤트를 저장하는 배열이 있음).deleteaddEventListener
  • nullIE 6/7/8 메모리 누수를 방지하기 위해 요소를 로 설정합니다 .
  • 그런 다음 요소를 제거합니다.

주로 내부 Google Maps API 이벤트를 언급하고 있습니다. developers.google.com/maps/documentation/javascript/…에 문서화 된 API 이벤트 메소드를 사용하여 추가 / 제거 / 트리거 할 수 있습니다 . 브라우저 addEventListener와 기능이 비슷하지만 맵에 특정한 많은 수의 사용자 정의 이벤트가 있습니다 (예 : "bounds_changed"및 맵 "크기 조정"이벤트와 같은 브라우저 이벤트에 연결되는 이벤트 핸들러 중 일부).
Chad Killingsworth

그런 다음 추가 된 이벤트 배열을 유지하고 이벤트 종류에 따라 수동으로 사용 removeEventListener하거나 제거 delete합니다.
Florian Margaine 2012 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.