Pregunta

Soy nuevo en JavaScript y todavía no estoy familiarizado con las funciones asincrónicas...

Estoy trabajando con node.js para crear un servidor de chat, esta es una parte de mi código que escucha getListConnected evento y cuando se activó buscar todos los conectados clients en un espacio de nombres determinado, y luego, para cada cliente, almaceno su 'nombre de usuario' en otra matriz, lo convierto en respuesta json y luego envío:

socket.on('getListConnected', function(msg){
                        var clients = namespace.clients();//get all client in that nsp
                        var usernames = Array() ;//init array

                        for(i in clients)//for each clients
                        {
                           clients[i].get("username", function(value){
                               usernames.push(value);
                            });
                        }
                       socket.emit('getListConnected',JSON.stringify(usernames));//send
                    });

El problema con este código es que el método client.get() es asincrónico, lo que significa que los nombres de usuario se envían vacíos.

¿Cómo puedo esperar los nombres de usuario hasta que se completen o cómo puedo esperar el ciclo hasta que finalice?

¿Fue útil?

Solución

Podrías usar middleware para promesas, algo como Azulejo, o puede mantener un contador para verificar si se han obtenido todos los nombres de usuario, algo como

socket.on('getListConnected', function (msg) {
    var clients   = namespace.clients();
    var usernames =  [];
    var counter1  =  0;
    var counter2  =  0;

    for (i in clients) {

        counter1++; // number of clients

        clients[i].get("username", function (value) {
            usernames.push(value);
            counter2++; // number of clients added to array

            if (counter1 === counter2) {
                socket.emit('getListConnected', JSON.stringify(usernames));
            }

        });
    }

});

Otros consejos

Aquí hay un ejemplo de Bluebird, personalizado para su situación:[toma prestado mucho de El ejemplo de Víctor Quinn]

Usando la misma definición de Promesa que usó Víctor:

var Promise = require('bluebird');

var promiseWhile = function(condition, action) {
    var resolver = Promise.defer();

    var loop = function() {
        if (!condition()) return resolver.resolve();
        return Promise.cast(action())
            .then(loop)
            .catch(resolver.reject);
    };

    process.nextTick(loop);

    return resolver.promise;
};

Instanciado con su llamada personalizada:

var i = 0;
promiseWhile(function() {
    return i < clients.length;
}, function(value) {
    return new Promise(function(resolve, reject) {
        clients[i].get("username", function(value){
                                       usernames.push(value);
            });
            i++;
            resolve();
    });
}).then(function() {
    console.log("usernames are: " + usernames);
});
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top