2010-06-13 13 views
22

Ho una funzione js per riprodurre qualsiasi suono dato usando l'interfaccia Audio (creando una nuova istanza per ogni chiamata).Javascript forza raccolta GC?/Oggetto a forza libera?

Questo funziona abbastanza bene, fino a circa la 32a chiamata (a volte meno). Questo problema è direttamente correlato al rilascio dell'istanza Audio. Lo so perché ho lasciato correre il tempo per il GC in Chromium e mi consentirà di riprodurre ancora altri 32 suoni.

Ecco un esempio di quello che sto facendo:

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

Ho anche questo, che funziona bene per le pagine che hanno meno di 32 PlaySound chiama:

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

ma questo non lavoro per quello che voglio fare (sostituire dinamicamente un div con altri contenuti (da file separati), che hanno ancora più suoni su di essi - 1. l'utilizzo della memoria potrebbe facilmente salire alle stelle, 2. molti suoni non giocheranno mai).

Ho bisogno di un modo per rilasciare immediatamente il suono. È possibile farlo? Non ho trovato alcun metodo di libero/chiudi/scarica per l'interfaccia audio.

Le pagine verranno visualizzate localmente, quindi il caricamento costante dei suoni non è affatto un fattore importante (e la maggior parte dei suoni è piuttosto breve).

risposta

15

Questa non è una risposta esauriente, ma alla domanda "Esiste un modo per forzare il motore cromo js per fare la raccolta dei rifiuti?", a chromium.org guy replied:

In generale, no, in base alla progettazione. Per scopi di test c'è un flag che è possibile passare sulla riga di comando per abilitare un comando javascript "window.gc()" per forzare la garbage collection .

--js-flags '--expose_gc'


UPDATE: Tuttavia, come @plash osservato in un commento qui sotto, questo flag funziona solo nella build di debug.

+0

Greeaat. Dovrei iniziare a utilizzare uno script per avviare Chromium per questo progetto (già utilizzando --allow-file-access-from-files in modo che possa aprire file dal filesystem locale). EDIT: lo considero un'ultima risorsa. – komiga

+0

@plash: assicurati di controllare [il post che ho collegato a] (https://groups.google.com/group/chromium-extensions/browse_thread/thread/5dc4be46e434116a?pli=1), perché la risposta che ho citato aveva ulteriori informazioni che potrebbero essere rilevanti. Non l'ho provato personalmente. –

+1

Non funziona in build non di debug. Ho appena provato. – komiga

18

I vedere almeno una (o due) difetti:

snd = new Audio(url); 

non ha var di fronte ad esso, così snd è assegnato alla portata globale. Questo di solito non è quello che vuoi: ingombrante lo spazio dei nomi globale e se un altro script (ad esempio un'estensione) usa incidentalmente snd, le cose saranno un disastro.

E questo è anche il motivo per

delete snd; 

non funziona: non è possibile delete global variables:

Quando le variabili e funzioni dichiarate diventano proprietà di un oggetto variabile - sia oggetto di attivazione (per codice funzione ) o Globale (per codice globale ), queste proprietà sono create con attributo DontDelete.

Quindi, utilizzare

var snd = new Audio(url); 

invece. A proposito, non è possibile forzare il motore JavaScript a fare la garbage collection.

+0

Ah, quello. Stavo testando qualcosa non molto tempo fa che mi ha fatto rimuovere il var. Era originariamente lì. MODIFICA: corretta. – komiga

+0

@plash: Ok, ma lascerò qui la mia risposta perché potrebbe essere utile ad altri utenti. –

+1

Non è vero! È possibile eliminare le variabili globali tramite 'delete window.snd'; – Adaptabi

2

L'eliminazione e l'impostazione su null non hanno funzionato neanche per me, quindi ho risolto il problema.

Ho funzionato per più di un suono allo stesso tempo. Per rilasciare le istanze, ogni suono deve essere un tag oggetto. Dinamicamente, aggiungi ogni Tag oggetto (suono) a un Div. Per rilasciare l'istanza, rimuovere dinamicamente il Tag dell'oggetto (suono) dal Div.

I indovina questo funziona perché un browser in genere implementa ogni tag come una sorta di oggetto. Quindi, quando elimino un tag, l'oggetto interno viene eliminato e rilascia tutte le risorse ad esso associate.

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

Per i parametri dell'oggetto completo andare here.

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

Giusto per correttezza: quei" Tag Oggetto "sono piuttosto [elementi oggetto] (http://www.w3.org/TR/html401/struct/objects.html#edef-OBJECT). Per favore non confondere [tag ed elementi] (http://perfectionkills.com/tag-is-not-an-element-or-is-it/)! –