2010-06-13 16 views
22

Tengo una función js para reproducir cualquier sonido usando la interfaz de Audio (creando una nueva instancia para cada llamada).Javascript force GC collection?/¿Objeto con fuerza libre?

Esto funciona bastante bien, hasta la llamada número 32 (a veces menos). Este problema está directamente relacionado con el lanzamiento de la instancia de Audio. Lo sé porque he dejado que se ejecute el GC en Chromium y me permita reproducir otros 32 o más.

He aquí un ejemplo de lo que estoy haciendo:

<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> 

también tengo esto, que funciona bien para las páginas que tienen menos de 32 reproducirSonido llama:

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

pero esto no será trabajo para lo que quiero hacer (dinámicamente reemplazar un div con otro contenido (de archivos separados), que tienen aún más sonidos en ellos - 1. el uso de la memoria se dispararía fácilmente, 2. muchos sonidos nunca se reproducirán).

Necesito una forma de liberar el sonido inmediatamente. ¿Es posible hacer esto? No he encontrado ningún método de liberación/cierre/descarga para la interfaz de audio.

Las páginas se verán localmente, por lo que la carga constante de sonidos no es un factor importante en absoluto (y la mayoría de los sonidos son bastante cortos).

Respuesta

15

Esta no es una respuesta exhaustiva, sino a la pregunta "¿Hay alguna manera de forzar el motor del cromo js hacer la recolección de basura?", a chromium.org guy replied:

En general, no, por diseño. Para fines de prueba, hay un indicador que puede pasar en la línea de comando para habilitar un comando de javascript "window.gc()" para forzar recolección de basura.

--js-flags '--expose_gc'


ACTUALIZACIÓN: Sin embargo, como se señaló en @plash un comentario más abajo, esta bandera sólo funcionará en versiones de depuración.

+0

Greeaat. Tendría que empezar a usar un script para iniciar Chromium para este proyecto (ya estoy usando --allow-file-access-from-files para poder abrir archivos desde el sistema de archivos local). EDITAR: Considero que este es un último recurso. – komiga

+0

@plash: asegúrese de verificar [la publicación a la que he vinculado] (https://groups.google.com/group/chromium-extensions/browse_thread/thread/5dc4be46e434116a?pli=1), porque la respuesta que cité tenía más información que puede ser relevante. No probé esto personalmente. –

+1

No funciona en compilaciones sin depuración. Solo lo probé. – komiga

18

que ver por lo menos una (o dos) defectos:

snd = new Audio(url); 

no tiene var en frente de ella, por lo snd se asigna al ámbito global. Por lo general, eso no es lo que quiere: desordena el espacio de nombre global y si otro script (por ejemplo, una extensión) usa incidentalmente snd, las cosas serán un desastre.

Y eso es también la razón por

delete snd; 

no funciona: no se puede delete global variables:

Cuando las variables y funciones declarados se convierten en propiedades de un objeto variable - ya sea objeto de activación (para Código de función) u Objeto global (para Código global), estas propiedades son creadas con el atributo DontDelete.

lo tanto, utilizar

var snd = new Audio(url); 

lugar. Por cierto, no puede forzar el motor de JavaScript para hacer la recolección de basura.

+0

Ah, eso. Estuve probando algo no hace mucho tiempo que me hizo eliminar la var. Originalmente estaba allí. EDITAR: Corregido. – komiga

+0

@plash: Ok, pero dejaré mi respuesta aquí ya que podría ser útil para otros usuarios. –

+1

¡Eso no es verdad! Puede eliminar variables globales a través de 'delete window.snd'; – Adaptabi

2

Simplemente eliminar y establecerlo en nulo tampoco funcionó para mí, así que hice una solución.

Lo tengo trabajando para más de un sonido al mismo tiempo. Para liberar las instancias, cada sonido debe ser una etiqueta de objeto. Dinámicamente, agregue cada etiqueta de objeto (sonido) a una div. Para liberar la instancia, elimine dinámicamente la etiqueta de objeto (sonido) de la div.

I guess esto funciona porque un navegador típicamente implementa cada etiqueta como un tipo de objeto. Entonces, cuando elimino una etiqueta, el objeto interno se elimina y libera los recursos asociados.

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

Para params objeto completos ir here.

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

Solo por corrección: esas" etiquetas de objeto "son más bien [elementos de objeto] (http://www.w3.org/TR/html401/struct/objects.html#edef-OBJECT). No confunda [etiquetas y elementos] (http://perfectionkills.com/tag-is-not-an-element-or-is-it/). –