Redis
 sql >> Datenbank >  >> NoSQL >> Redis

Node.js &Redis; Warten auf das Ende einer Schleife

Ich würde den Weg gehen, den Sie in Ihrer Frage vorschlagen, und Ihrer Abruffunktion einen benutzerdefinierten Rückruf anhängen:

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
});

Das ist wahrscheinlich die effizienteste Methode; alternativ könnten Sie sich auf ein while der alten Schule verlassen Schleife, bis die Daten bereit sind:

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);
    }
});

Wir verwenden process.nextTick anstelle eines tatsächlichen while um sicherzustellen, dass andere Anfragen in der Zwischenzeit nicht blockiert werden; Aufgrund der Single-Thread-Natur von Javascript ist dies der bevorzugte Weg. Ich werfe dies der Vollständigkeit halber ein, aber die erstere Methode ist effizienter und passt besser zu node.js, also machen Sie es, es sei denn, es handelt sich um eine größere Neufassung.

Es ist nichts wert, dass beide Fälle auf asynchrone Rückrufe angewiesen sind, was bedeutet, dass jeder Code außerhalb möglicherweise immer noch ausgeführt werden kann, bevor andere fertig sind. Zum Beispiel mit unserem ersten Snippet:

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

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

console.log("hello world");

Das letzte console.log wird fast garantiert ausgeführt, bevor unser an getStudentsData übergebener Callback ausgelöst wird. Problemumgehung? Entwerfen Sie dafür, so funktioniert node.js. In unserem obigen Fall ist es einfach, wir würden nur nur console.log aufrufen in unserem Rückruf an getStudentsData übergeben und nicht außerhalb. Andere Szenarien erfordern Lösungen, die etwas mehr von der traditionellen prozeduralen Codierung abweichen, aber sobald Sie sich damit vertraut gemacht haben, werden Sie feststellen, dass ereignisgesteuert und nicht blockierend tatsächlich eine ziemlich leistungsstarke Funktion ist.