Javascript заставить сбор GC?/ Принудительно освободить объект? - PullRequest
24 голосов
/ 14 июня 2010

У меня есть функция js для воспроизведения любого данного звука с использованием аудио интерфейса (создание нового экземпляра для каждого вызова).

Это работает довольно хорошо, вплоть до 32-го вызова (иногда меньше).Эта проблема напрямую связана с выпуском экземпляра Audio.Я знаю это, потому что я дал время для запуска GC в Chromium, и это позволит мне снова воспроизвести еще 32 или более звука.

Вот пример того, что я делаю:

<html><head>
<script type="text/javascript">
function playSound(url) {
    var snd = new Audio(url);
    snd.play();
    snd = null;
}
</script>
</head>

<body>
<a href="#" onclick="playSound('blah.mp3');">Play sound</a>
</body></html>

У меня также есть это, которое хорошо работает для страниц, которые имеют менее 32 вызовов playSound:

var AudioPlayer = {
    cache: {},
    play: function(url) {
        if (!AudioPlayer.cache[url])
            AudioPlayer.cache[url] = new Audio(url);
        AudioPlayer.cache[url].play();
    }
};

Но это не будет работать для того, что я хочу сделать (динамически заменить div на другойконтент (из отдельных файлов), на котором есть еще больше звуков - 1. использование памяти легко взлетит до небес, 2. многие звуки никогда не будут воспроизводиться).

Мне нужен способ немедленно выпустить звук.Можно ли сделать это?Я не нашел метода free / close / unload для интерфейса Audio.

Страницы будут просматриваться локально, поэтому постоянная загрузка звуков вообще не является большим фактором (и большинство звуков довольно короткие).

Ответы [ 3 ]

20 голосов
/ 14 июня 2010

Я вижу по крайней мере один (или два) недостатка:

snd = new Audio(url);

не имеет var перед ним, поэтому snd назначается глобальной области видимости.Обычно это не то, что вам нужно: оно загромождает глобальное пространство имен, и если другой сценарий (например, расширение) случайно использует snd, все будет беспорядочно.

И вот почему

delete snd;

не работает: вы не можете удалить глобальные переменные :

Когда объявленные переменные и функции становятся свойствами объекта Variable - либо объект Activation (для функциикод) или глобальный объект (для глобального кода), эти свойства созданы с атрибутом DontDelete .

Итак, используйте вместо этого

var snd = new Audio(url);

.Кстати, вы не можете заставить движок JavaScript выполнять сборку мусора.

17 голосов
/ 14 июня 2010

Это не исчерпывающий ответ, но на вопрос «Есть ли способ заставить двигатель chrome js выполнить сборку мусора?», парень chromium.org ответил :

Как правило, нет, по замыслу. Для целей тестирования есть флаг, который можно передать в командной строке, чтобы включить команду JavaScript "window.gc ()", чтобы заставить вывоз мусора.

--js-flags '--expose_gc'


ОБНОВЛЕНИЕ: Однако, как @ plash отмечено в комментарии ниже, этот флаг будет работать только в отладочных сборках.

2 голосов
/ 14 июня 2010

Простое удаление и установка его в null также не работали для меня, поэтому я сделал обходной путь.

Я получил его для более чем одного звука одновременно .Чтобы освободить экземпляры, каждый звук должен быть тегом объекта.Динамически добавляйте каждый тег объекта (звук) в Div.Чтобы освободить экземпляр, динамически удалите тег объекта (звук) из Div.

I предположите , это работает, потому что браузер обычно реализует каждый тег как некоторый объект.Поэтому, когда я удаляю тег, внутренний объект удаляется и высвобождает все ресурсы, связанные с ним.

<!--HTML: This will contains object sounds-->
<Div id="sounds"></Div>

//Javacript, using jQuery
//Create and play an MP3
var id_event = 1234; //Keep and incrementing a counter might do, I use an Event Id from my app.
var objSound = "<object width='1' height='1' id='AUDIOIE" + id_event 
        + " type='application/x-oleobject'  AND_MORE_PARAMS_TO_PLAY_A_MP3"
        + "/>";
$(objSound).appendTo('#sounds');

Для получения полных параметров объекта перейдите здесь .

//To Stop an MP3 and release it instance.
$('#AUDIOIE' + id_event).empty().remove();
...