Tengo un código en el que obtengo la duración de un archivo .wav y lo proceso. Para hacer esto, intento cargar los metadatos del archivo.
onload = () => { // make an Audio object which represents a wav file const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); let audio = new Audio(urlParams.get('src')); audio.volume = urlParams?.get('volume') ?? 1; audio.play() // log the duration of the wav file console.log(getDuration(audio)) // do processing on the duration of the file setTimeout(() => { close(); }, urlParams?.get('duration') ?? getDuration(audio)); } async function getDuration(audio) { let audioTag = document.getElementById('get_duration') audioTag.src = audio.src // attempt to return duration audioTag.addEventListener('loadedmetadata', function(){ return Promise.resolve(audioTag.duration) }) } Esto falla porque hay un retorno implícito undefined al final de la función getDuration , lo que hace que devuelva un objeto Promise indefinido antes de que ocurra el evento de loadedmetadata .
Podría usar una función de devolución de llamada así:
onload = () => { // make an Audio object which represents a wav file // log the duration of the wav file console.log(getDuration(audio, process)) } function process(duration) { // do processing on the duration of the file } function getDuration(audio, func) { let audioTag = document.getElementById('get_duration') audioTag.src = audio.src // duration successfully obtained audioTag.addEventListener('loadedmetadata', function(){ func(audioTag.duration) }) }pero esto parece poco elegante y no escalable, especialmente considerando que obtener la duración de un archivo debería ser simple.
¿Hay alguna forma de devolver la duración de un archivo wav (o esperar un evento en general) sin usar una función de devolución de llamada?
Encontré una solución de https://stackoverflow.com/a/70789108/16236499 .
onload = () => { // make an Audio object which represents a wav file // log the duration of the wav file console.log(getDuration(audio)) // do processing on the duration of the file } // https://stackoverflow.com/a/70789108/16236499 async function getDuration(audio) { let audioTag = document.getElementById('get_duration') audioTag.src = audio.src await getPromiseFromEvent(audioTag, 'loadedmetadata') return audioTag.duration } function getPromiseFromEvent(item, event) { return new Promise((resolve) => { const listener = () => { item.removeEventListener(event, listener) console.log(item.duration) resolve() } item.addEventListener(event, listener) }) }