es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué un “await sleep” sale de un bucle “for” antes de tiempo?

Intento crear un efecto de desvanecimiento para una aplicación de música cuando hago clic en el botón siguiente/anterior.
Tengo esta función de sleep:

const sleep = (milisegundos) => new Promise((resolve) => setTimeout(resolve, milisegundos));

La función cuando se pulsa el botón:

function siguienteCancion() {
indiceCancion++;
if (indiceCancion > canciones.length - 1) {
indiceCancion = 0;
}
desvanecer(audio);
cargarCancion(canciones[indiceCancion]);
reproducirCancion();
aparecer(audio);
}

Y las funciones de desvanecimiento:

async function desvanecer(sonido) {

for (var i = 1.0; i > 0; i-= 0.01)
{
    console.log(i);
    console.log(sonido.volumen);
    sonido.volumen = i;
    await sleep(2000);
}
}

async function aparecer(sonido) {

for (var i = 0; i <= 1; i+= 0.01)
{
    console.log(i);
    console.log(sonido.volumen);
    sonido.volumen = i;
    await sleep(100);
}
}

El problema es que desvanecer no funciona en absoluto, solo realiza una iteración en el bucle for y luego sale.
Mientras tanto, aparecer funciona perfectamente. No entiendo por qué. Por cierto, este es mi primer proyecto de JavaScript como hobby.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Hay algunos problemas potenciales con la implementación actual de la función fadeOut:

    1. La condición del bucle for está comprobando si i > 0, pero dado que i es un número de punto flotante, es posible que no llegue exactamente a 0 debido a problemas de precisión. Es más seguro establecer un valor umbral y comprobar cuando i esté por debajo de ese umbral.
    2. La instrucción await sleep(2000) dentro del bucle for está haciendo que toda la función se pause durante 2 segundos en cada iteración. Esto significa que el bucle for tardará mucho tiempo en completarse e incluso es posible que no llegue al final antes de que la función agote el tiempo de espera o sea interrumpida por otro código.
    3. La función fadeOut se llama inmediatamente antes de las funciones loadSong y playSong, por lo que es posible que el audio no tenga tiempo suficiente para desvanecerse antes de que empiece a reproducirse la nueva canción.

    Para solucionar estos problemas, podrías intentar modificar la función fadeOut para usar un bucle while en lugar de un bucle for y comprobar un valor umbral en lugar de llegar exactamente a 0. También podrías mover las funciones loadSong y playSong dentro de la función fadeOut y utilizar async/await para asegurarte de que no se inicien hasta que se haya completado el efecto fadeOut. Aquí tienes un ejemplo de implementación:

    async function fadeOut(soundtrack) {
      let volume = soundtrack.volume;
      while (volume > 0.01) {
        volume -= 0.01;
        soundtrack.volume = volume;
        await sleep(50); // menor retraso para un efecto más suave
      }
      soundtrack.volume = 0;
      loadSong(songs[songIndex]);
      await sleep(500); // agregar un pequeño retraso antes de comenzar la nueva canción
      playSong();
    }
    
    async function nextSong() {
      songIndex++;
      if (songIndex > songs.length - 1) {
        songIndex = 0;
      }
      await fadeOut(audio); // esperar a que se complete el efecto fadeOut
      fadeIn(audio); // comenzar fadeIn inmediatamente después de fadeOut
    }
    

    Ten en cuenta que la función fadeOut ahora recibe el elemento de audio como argumento, por lo que deberás actualizar la función nextSong para pasar el elemento correcto. Además, he agregado un pequeño retraso antes de comenzar la nueva canción después del efecto fadeOut, solo para asegurarme de que el audio se haya desvanecido por completo antes de comenzar la nueva canción. Es posible que debas ajustar el tiempo de retraso según tu caso de uso específico.

Comments are closed.