Saya baru-baru ini mengembangkan aplikasi seluler html5. Aplikasi tersebut adalah satu halaman tempat peristiwa perubahan hash navigasi menggantikan seluruh DOM. Salah satu bagian dari aplikasinya adalah Google Map menggunakan API v3. Sebelum div peta dihapus dari DOM, saya ingin menghapus event handler / listener dan mengosongkan memori sebanyak mungkin karena pengguna tidak dapat kembali ke bagian itu lagi.
Apa cara terbaik untuk menghancurkan instance peta?
javascript
google-maps-api-3
Chad Killingsworth
sumber
sumber
Jawaban:
Saya menambahkan jawaban kedua atas pertanyaan ini, karena saya tidak ingin menghapus bolak-balik yang kami miliki melalui komentar tindak lanjut pada jawaban saya sebelumnya.
Namun baru-baru ini saya menemukan beberapa informasi yang secara langsung menjawab pertanyaan Anda, jadi saya ingin berbagi. Saya tidak tahu apakah Anda menyadarinya, tetapi selama Video Jam Kerja Google Maps API 9 Mei 2012 , Chris Broadfoot dan Luke Mahe dari Google membahas pertanyaan ini dari stackoverflow. Jika Anda menyetel pemutaran video ke 12:50, itu adalah bagian di mana mereka membahas pertanyaan Anda.
Pada dasarnya, mereka mengakui bahwa itu adalah bug, tetapi juga menambahkan bahwa mereka tidak benar-benar mendukung kasus penggunaan yang melibatkan pembuatan / penghancuran contoh peta yang berurutan. Mereka sangat menyarankan untuk membuat satu contoh peta dan menggunakannya kembali dalam skenario apa pun seperti ini. Mereka juga berbicara tentang menyetel peta ke null, dan secara eksplisit menghapus event listener. Anda mengungkapkan kekhawatiran tentang pendengar acara, saya pikir hanya menyetel peta ke nol saja sudah cukup, tetapi tampaknya kekhawatiran Anda valid, karena mereka menyebutkan pendengar acara secara khusus. Mereka juga merekomendasikan untuk menghapus DIV yang menahan peta juga.
Bagaimanapun, hanya ingin meneruskan ini dan memastikan itu termasuk dalam diskusi stackoverflow dan berharap ini membantu Anda dan orang lain-
sumber
The jawaban resmi adalah Anda tidak. Contoh peta dalam aplikasi satu halaman harus digunakan kembali dan tidak dihancurkan lalu dibuat ulang.
Untuk beberapa aplikasi halaman tunggal, ini mungkin berarti merancang ulang solusi sedemikian rupa sehingga setelah peta dibuat, peta tersebut mungkin tersembunyi atau terputus dari DOM, tetapi tidak pernah dimusnahkan / dibuat ulang.
sumber
Karena tampaknya Anda tidak dapat benar-benar menghancurkan contoh peta, cara untuk mengurangi masalah ini jika
menyimpan sekumpulan contoh peta. Pool terus melacak instance yang digunakan, dan ketika diminta instance baru, ia memeriksa apakah ada instance peta yang tersedia gratis: jika ada, itu akan mengembalikan yang sudah ada, jika tidak, itu akan membuat contoh peta baru dan mengembalikannya, menambahkannya ke kolam. Dengan cara ini Anda hanya akan memiliki jumlah maksimum contoh yang sama dengan jumlah maksimum peta yang pernah Anda tampilkan secara bersamaan di layar. Saya menggunakan kode ini (membutuhkan 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 } } }
Anda meneruskan opsi peta awal (sesuai argumen kedua dari konstruktor google.maps.Map), dan mengembalikan instance peta (tempat Anda dapat memanggil fungsi yang berkaitan dengan google.maps.Map), dan container, yang mana Anda dapat mengatur gaya menggunakan kelas "myDivClassHereForStyling", dan Anda dapat menambahkan DOM secara dinamis. Jika Anda perlu mengatur ulang sistem, Anda dapat menggunakan mapInstancesPool.reset (). Ini akan mengatur ulang penghitung ke 0, sambil menyimpan semua contoh yang ada di kumpulan untuk digunakan kembali. Dalam aplikasi saya, saya perlu menghapus semua peta sekaligus dan membuat satu set peta baru, jadi tidak ada fungsi untuk mendaur ulang contoh peta tertentu: jarak tempuh Anda mungkin berbeda. Untuk menghapus peta dari layar, saya menggunakan detach jQuery, yang tidak merusak container peta.
Dengan menggunakan sistem ini, dan menggunakan
google.maps.event.clearInstanceListeners(window); google.maps.event.clearInstanceListeners(document);
dan berlari
google.maps.event.clearInstanceListeners(divReference[0]); divReference.detach()
(di mana divReference adalah objek jQuery div yang dikembalikan dari Instance Pool) pada setiap div yang saya hapus, saya berhasil menjaga penggunaan memori Chrome lebih atau kurang stabil, berlawanan dengan peningkatan setiap kali saya menghapus peta dan menambahkan yang baru.
sumber
Saya akan menyarankan untuk menghapus konten div peta dan menggunakan
delete
variabel yang memegang referensi ke peta, dan mungkin secara eksplisitdelete
menggunakan event listener.Namun, ada bug yang diketahui , dan ini mungkin tidak berfungsi.
sumber
delete
menambah banyak (lihat stackoverflow.com/q/742623/1314132 ), tetapi itu benar-benar tidak ada salahnya. Pada akhirnya, pertanyaannya adalah: apakah ada referensi ke objek tersebut? Jika ya, sampah tidak akan dikumpulkan.GUnload()
menghapus semua referensi internal API.delete
itu bukanlah perbaikan. Mereka harus memperbaiki besarnya sehingga membuat referensi tidak dapat dijangkau berfungsi sebagaimana mestinya atau menambahkan fungsi baru yang menyediakan fungsionalitas yang Anda jelaskanGUnload()
.delete
daninnerHTML
menghapus memori tidak sepenuhnya menghapus. Sayangnya ini bukan bug dengan prioritas tinggi.Karena google tidak menyediakan gunload () untuk api v3 lebih baik gunakan iframe di html dan tetapkan map.html sebagai sumber untuk iframe ini. setelah digunakan jadikan src sebagai null. Itu pasti akan membebaskan memori yang dikonsumsi oleh peta.
sumber
Saat Anda menghapus
div
, itu menghilangkan panel tampilan dan peta akan menghilang. Untuk menghapus instance peta, cukup pastikan bahwa referensi Anda ke peta disetel kenull
dan semua referensi ke bagian lain dari peta disetel kenull
. Pada titik itu, pengumpulan sampah JavaScript akan melakukan pembersihan, seperti yang dijelaskan di: Bagaimana cara kerja pengumpulan sampah di JavaScript? .sumber
null
, tetapi referensi ke hal lain. Jadi, jika referensi marker disetel kenull
, sehingga tidak dapat dijangkau , tidak ada cara untuk menjangkau pemroses peristiwa. Ini mungkin masih terhubung ke peta, tetapi peta tidak dapat dijangkau, jadi itu hanya sebongkah besar memori yang pada dasarnya menjadi yatim piatu. Ini sama dengan mengaturArray.length = 0
; Jika tidak ada referensi lain untuk anggota, mereka hanya membentuk kelompok memori yatim piatu yang memenuhi syarat untuk pengumpulan sampah.Saya kira yang Anda bicarakan
addEventListener
. Saat Anda menghapus elemen DOM, beberapa browser membocorkan peristiwa ini dan tidak menghapusnya. Inilah mengapa jQuery melakukan beberapa hal saat menghapus sebuah elemen:removeEventListener
. Itu berarti mempertahankan array dengan event listener yang ditambahkannya ke elemen ini.onclick
,,onblur
dll) yang digunakandelete
pada elemen DOM ketikaaddEventListener
tidak tersedia (masih, ia memiliki larik tempat menyimpan peristiwa yang ditambahkan).null
untuk menghindari kebocoran memori IE 6/7/8.sumber
removeEventListener
ataudelete
bergantung pada jenis peristiwa.