sql >> Base de Datos >  >> NoSQL >> Redis

Node.js y Redis; Esperando a que termine un bucle

Seguiría la ruta que sugiere en su pregunta y adjuntaría una devolución de llamada personalizada a su función de búsqueda:

function getStudentsData(callback) {
    var setList = [];
    var dataList = [];

    redisClient.smembers("student_setList", function(err,result) {
        setList = result; //id's of students

        for(var i = 0; i < setList.length; i++) {
            redisClient.get(setList[i], function(err, result) {
                if(err) {
                    console.log("Error: "+err);
                } else {
                    tempObject = JSON.parse(result);
                    if(tempObject.name != null) {
                        dataList.push(tempObject);
                    }
                }
            });     
        }

        if(dataList.length == setList.length) {
            if(typeof callback == "function") {
                callback(dataList);
            }
            console.log("getStudentsData: done");
        } else {
            console.log("getStudentsData: length mistmach");
        }

    });
}

getStudentsData(function(dataList) {
    console.log("Goes here after checking every single object");
    console.log(dataList.length);
    //More code here
});

Ese es probablemente el método más eficiente; alternativamente, podría confiar en un while de la vieja escuela bucle hasta que los datos estén listos:

var finalList = [];
var list = [0];

redisClient.smembers("student_list", function(err,result) {
    list = result; //id's of students
    var possibleStudents = [];

    for(var i = 0; i < list.length; i++) {
        redisClient.get(list[i], function(err, result) {
            if(err) {
                console.log("Error: "+err);
            } else {
                tempObject = JSON.parse(result);
                if(tempObject.name != null) {
                    finalList.push(tempObject);
                }
            }
        });     
    }
});


process.nextTick(function() {
    if(finalList.length == list.length) {
        //Done
        console.log("Goes here after checking every single object");
        console.log(dataList.length);
        //More code here
    } else {
        //Not done, keep looping
        process.nextTick(arguments.callee);
    }
});

Usamos process.nextTick en lugar de un while real para asegurarse de que otras solicitudes no se bloqueen mientras tanto; debido a la naturaleza de subproceso único de Javascript, esta es la forma preferida. Incluyo esto en aras de la exhaustividad, pero el método anterior es más eficiente y encaja mejor con node.js, así que hazlo a menos que se trate de una reescritura importante.

No vale la pena que ambos casos se basen en devoluciones de llamada asíncronas, lo que significa que cualquier código externo aún puede ejecutarse antes de que otros terminen. Por ejemplo, usando nuestro primer fragmento:

function getStudentsData(callback) {
    //[...]
}

getStudentsData(function(dataList) {
    //[...]
});

console.log("hello world");

Casi se garantiza que ese último console.log se ejecutará antes de que se active nuestra devolución de llamada pasada a getStudentsData. ¿Solución alterna? Diseñe para ello, así es como funciona node.js. En nuestro caso anterior, es fácil, simplemente llamaríamos a console.log solo en nuestra devolución de llamada pasada a getStudentsData y no fuera de ella. Otros escenarios requieren soluciones que se alejen un poco más de la codificación de procedimientos tradicional, pero una vez que comprenda la idea, descubrirá que estar basado en eventos y no bloquear es en realidad una característica bastante poderosa.