Предотвратить утечку памяти от повторного $.ajax( { dataType: 'script' })
Я пишу небольшое локальное веб-приложение, которое ожидает прерывистого доступа к сети. Имея это в виду, я проверяю, не загружается ли наша внешняя зависимость (Google Maps), и повторяю попытку через 10 секунд. Краткое описание:
// Assume the worst
var mapsSuccess = false;
// Only gets invoked by maps success
function initialize(){
// Set the flag to prevent continuous recursion of the previous function
mapsSucess = true;
/* application init */
}
// Invoke immediately
( function mapsCall(){
// Maybe we don't need this...
if( mapsSuccess === true ){
return;
}
$.ajax( {
cache : true,
dataType : 'script',
// `callback` param specifies function to call on successful execution
url : googleMapsUri + '&callback=initialize'
} );
// Run this function again in 10 seconds to see if we succeeded
setTimeout( mapsCall, 10000 )
}() );
Проблема в худшем случае, когда мы не можем загружать карты часами. Существует резервный автономный контент, но в настоящее время утечка памяти в конечном итоге приводит к сбою браузера. Изучение временной шкалы в инструментах разработчика Chrome, источник очевиден:
Каждый раз mapsCall
повторно вызывается, новые узлы DOM и новые слушатели событий вызываются. Я хотел бы удалить их и удалить любые прослушиватели событий, которые связаны (по иронии судьбы, мой код не устанавливает прослушиватели событий), поэтому я установил это в mapsCall
тело:
$( 'script[async][src*="callback=initialize"]' ).off().remove();
Это эффективно удаляет избыточные элементы сценария, но не приводит к утечке памяти из-за количества прослушивателей событий. Я пытался выяснить, где эти таинственные слушатели событий связаны с помощью $._data( element, 'events' )
, но они не на самих сценариях, document
, window
или корневые элементы (html
, body
) так что я в растерянности.