0

antes que nada comentar que ya he leído otras preguntas similares pero no han resuelto mi problema, entre ellas ¿Cómo ralentizar un loop for en javascript? y ¿Por qué el valor i siempre es 5 - JS?

Cómo el código es muy largo compartiré la parte en la cual tengo el problema y una imagen con la descripción de que hace cada función o variable mencionada.

function updateHistory(url) {
            $(".history ul li", thisObj).remove();
                        
            if (settings.version == 1) {} else if (settings.version == 2) {
                //cuando llamo a la función borro la clase .row-wpr y desaparecen todas las filas del DOM
                $(".row-wpr", thisObj).remove();
                            
                $.ajax({
                    dataType: 'jsonp',
                    url: url,
                    success: function(data) {
                        //fijo el número de filas a agregar en 5
                        data.length = 6;
                        for (let i = 1; i < data.length; i++) {
                            var rowNum = i;
                            var listVal = rowNum;
                            var songtitle = data[i].title;
                            var songtitleSplit = songtitle.split('-');
                            var artist = songtitleSplit[0];
                            var title = songtitleSplit[1];
                            //agrega al DOM una fila con el titulo de la canción (title), artista (artist) y un número (listVal)
                            $(".history-wpr", thisObj).append("<div class='row-wpr'><div class='history-cover' id='row" + rowNum + "'></div><div class='history-track-info'><div class='history-songtitle'>" + title + "</div><div class='history-artist-name'>" + artist + "</div></div><div class='rowNum'>" + listVal + "</div></div>");
                            //si se ha elegido mostrar las caratulas las obtengo con la función getImageList
                            if (settings.artwork == !0) {
                                getImageList(artist, title, rowNum);
                                } else {  //de lo contrario coloco un logo predefinido 
                                $('#row' + i, thisObj).css({
                                    "background-image": "url(" + settings.logo + ")",
                                    "background-size": "100% 100%"
                                })
                            }
                        }
                    }
                })
            }
        }

imagen DOM

Resumen del problema a resolver

Esta parte del código lo que hace es mostrar las últimas 5 canciones reproducidas, cada vez que se llama a la función que realiza el update se borran las 5 canciones anteriores y se imprimen nuevamente las filas eliminando la última y poniendo en primer lugar la canción que se estaba reproduciendo antes del update. Las 5 filas se imprimen "simultáneamente" (por la velocidad del bucle) como se muestra en la imagen.

Que deseo ?

Deseo ralentizar el bucle de tal manera que se muestre la fila 1 (con su imagen a la izquierda) transcurran 3 segundos y se muestre la fila 2 y así sucesivamente hasta completar las 5.

Qué he intentado ?

Como los datos del título, autor y número se obtienen con $(".history-wpr", thisObj).append y las imágenes se obtienen con la función getImageList intenté poner una función setTimeout en ambos lugares, sustituyendo ambas líneas de código mostradas arriba por estas:

Tiempo para título, autor y número

setTimeout(function() { 
$(".history-wpr", thisObj).append("<div class='row-wpr'><div class='history-cover' id='row" + rowNum + "'></div><div class='history-track-info'><div class='history-songtitle'>" + title + "</div><div class='history-artist-name'>" + artist + "</div></div><div class='rowNum'>" + listVal + "</div></div>"); },i * 3000 );

Tiempo para imágenes

setTimeout(getImageList(artist, title, rowNum),i * 3000 );

El asunto es que "i" siempre vale 5 (lo mismo que sucedía en otra pregunta relacionada que cité al comienzo), aún usando let en lugar de var que fue la solución que se brindó en en ese momento. Por tal motivo se repite 5 veces los datos de la última canción y lo curioso que no se muestra ninguna imagen, desconozco el motivo ya que no da ningún error.

image luego del cambio

Juan
  • 87
  • 7

1 Answers1

0

Ya logré solucionarlo y compartiré esta solución para todos aquellos usuarios que deseen ralentizar un bucle for en JQuery o JavaScript.

Para resolver este problema, debe usar el cierre: invoque inmediatamente la función a la que se llamará en cada iteración con "i" como param y setTimeout dentro de esta función. En este caso, el parámetro que pasó se almacenará en el alcance y podría usarse en la devolución de llamada de tiempo de espera:

for (var i=1; i<6; i++) (function(t) {
    setTimeout(function() {
    //hacer cualquier cosa con t (aquí va el código que quieres iterar)
    }, t*3000)
}(i))

Con este ejemplo se vería aproximadamente lo que ocurre con la función:

for (var i=1; i<6; i++) (function(t) {
    setTimeout(function() {
    console.log(t);
    }, t*3000)
}(i))

Para mi caso particular tuve que eliminar un condicional que no es de importancia en mi código porque no logré obtener las imágenes poniendo dos SetTimeout independientes y la solución que funcionó fue esta:

function updateHistory(url) {
            $(".history ul li", thisObj).remove();
                        
            if (settings.version == 1) {} else if (settings.version == 2) {
                //cuando llamo a la función borro la clase .row-wpr y desaparecen todas las filas del DOM
                $(".row-wpr", thisObj).remove();
                            
                $.ajax({
                    dataType: 'jsonp',
                    url: url,
                    success: function(data) {
                        //fijo el número de filas a agregar en 5
                        data.length = 6;
                        for (var i = 1; i < data.length; i++) (function(t) {
                            var rowNum = i;
                            var listVal = rowNum;
                            var songtitle = data[i].title;
                            var songtitleSplit = songtitle.split('-');
                            var artist = songtitleSplit[0];
                            var title = songtitleSplit[1];
                            //agrega al DOM una fila con el titulo de la canción (title), artista (artist) y un número (listVal)
                            setTimeout(function() {
                            $(".history-wpr", thisObj).append("<div class='row-wpr'><div class='history-cover' id='row" + rowNum + "'></div><div class='history-track-info'><div class='history-songtitle'>" + title + "</div><div class='history-artist-name'>" + artist + "</div></div><div class='rowNum'>" + listVal + "</div></div>"); 
                            getImageList(artist, title, rowNum);
                            }, t*3000)
                        }(i))
                    }
                })
            }
        }
Juan
  • 87
  • 7