Подтвердить что ты не робот

Сборник Javascript GC GC?/Сильно свободный объект?

У меня есть функция 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.

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

4b9b3361

Ответ 1

Это не исчерпывающий ответ, но на вопрос "Есть ли способ заставить движок хрома js делать сборку мусора?", хром .org парень ответил:

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

--js-flags '--expose_gc'


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

Ответ 2

Я вижу хотя бы один (или два) недостатка:

snd = new Audio(url);

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

И вот почему

delete snd;

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

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

Итак, используйте

var snd = new Audio(url);

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

Ответ 3

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

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

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

<!--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();