Asíncrono para ciclo en JavaScript

Resuelto Marry Hoffser asked hace 14 años • 13 respuestas

Necesito un bucle que espere una llamada asíncrona antes de continuar. Algo como:

for ( /* ... */ ) {

  someFunction(param1, praram2, function(result) {

    // Okay, for cycle could continue

  })

}

alert("For cycle ended");

¿Cómo podría hacer esto? ¿Tienes alguna idea?

Marry Hoffser avatar Nov 27 '10 04:11 Marry Hoffser
Aceptado

No puede mezclar sincrónico y asincrónico en JavaScript si bloquea el script, bloquea el navegador.

Tienes que seguir el camino completo del evento aquí, afortunadamente podemos ocultar las cosas feas.

EDITAR: Se actualizó el código.

function asyncLoop(iterations, func, callback) {
    var index = 0;
    var done = false;
    var loop = {
        next: function() {
            if (done) {
                return;
            }

            if (index < iterations) {
                index++;
                func(loop);

            } else {
                done = true;
                callback();
            }
        },

        iteration: function() {
            return index - 1;
        },

        break: function() {
            done = true;
            callback();
        }
    };
    loop.next();
    return loop;
}

Esto nos proporcionará un asincrónico loop; por supuesto, puede modificarlo aún más para tomar, por ejemplo, una función para verificar la condición del bucle, etc.

Ahora vamos a la prueba:

function someFunction(a, b, callback) {
    console.log('Hey doing some stuff!');
    callback();
}

asyncLoop(10, function(loop) {
    someFunction(1, 2, function(result) {

        // log the iteration
        console.log(loop.iteration());

        // Okay, for cycle could continue
        loop.next();
    })},
    function(){console.log('cycle ended')}
);

Y la salida:

Hey doing some stuff!
0
Hey doing some stuff!
1
Hey doing some stuff!
2
Hey doing some stuff!
3
Hey doing some stuff!
4
Hey doing some stuff!
5
Hey doing some stuff!
6
Hey doing some stuff!
7
Hey doing some stuff!
8
Hey doing some stuff!
9
cycle ended
Ivo Wetzel avatar Nov 26 '2010 22:11 Ivo Wetzel

Simplifiqué esto:

FUNCIÓN:

var asyncLoop = function(o){
    var i=-1;

    var loop = function(){
        i++;
        if(i==o.length){o.callback(); return;}
        o.functionToLoop(loop, i);
    } 
    loop();//init
}

USO:

asyncLoop({
    length : 5,
    functionToLoop : function(loop, i){
        setTimeout(function(){
            document.write('Iteration ' + i + ' <br>');
            loop();
        },1000);
    },
    callback : function(){
        document.write('All done!');
    }    
});

EJEMPLO: http://jsfiddle.net/NXTv7/8/

wilsonpage avatar Oct 04 '2011 22:10 wilsonpage