У меня есть функция js для проигрывания любого данного звука с помощью Аудиоинтерфейса (создающий новый экземпляр для каждого вызова).
Это работает вполне хорошо, до приблизительно 32-й вызов (иногда меньше). Эта проблема непосредственно связана с выпуском Аудио экземпляра. Я знаю это, потому что я позволил времени для GC в Хроме работать, и он позволит мне играть еще приблизительно 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();
}
};
Но это не будет работать на то, что я хочу сделать (динамично заменяют отделение другим содержанием (из отдельных файлов), которые имеют еще больше звуков на них - 1. использование памяти легко взлетело бы, 2. много звуков никогда не будут играть).
Мне нужен способ сразу выпустить звук. Действительно ли возможно сделать это? Я нашел, не освобождают/закрывают/разгружают метод для Аудиоинтерфейса.
Страницы будут просмотрены локально, таким образом, постоянная загрузка звуков не будет большим фактором вообще (и большинство звуков довольно коротко).
Это не исчерпывающий ответ, но на вопрос «Есть ли способ заставить движок chrome js выполнять сборку мусора?», парень с сайта chromium.org ответил :
В общем, нет, по замыслу. Для тестирования есть флаг, который можно передать в командной строке, чтобы разрешить команде javascript "window.gc ()" принудительно вывоз мусора.
- js-flags '--expose_gc'
ОБНОВЛЕНИЕ: Однако, как @ plash отмечалось в комментарии ниже, этот флаг будет работать только в отладочных сборках.
Простое удаление и установка значения 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();
Я вижу по крайней мере один (или два) недостатка:
snd = new Audio(url);
не имеет перед ним var
, поэтому snd
назначается глобальной области. Обычно это не то, что вам нужно: это загромождает глобальное пространство имен, и если другой сценарий (например, расширение) случайно использует snd
, все будет в беспорядке.
И поэтому
delete snd;
не работает: вы не можете удалить глобальные переменные :
Когда объявлены переменные и функции стать свойствами объекта переменной - либо объект активации (для Код функции) или Глобальный объект (для Глобальный код), эти свойства создан с атрибутом DontDelete .
Поэтому используйте вместо него
var snd = new Audio(url);
. Кстати, вы не можете заставить движок JavaScript выполнять сборку мусора.