sql >> Database >  >> NoSQL >> Redis

Node.js &Redis; Wachten tot een lus is afgelopen

Ik zou de route volgen die u in uw vraag voorstelt en een aangepaste callback toevoegen aan uw ophaalfunctie:

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

Dat is waarschijnlijk de meest efficiënte methode; je kunt ook vertrouwen op een oude school while loop totdat de gegevens klaar zijn:

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

We gebruiken process.nextTick in plaats van een echte while om ervoor te zorgen dat andere verzoeken in de tussentijd niet worden geblokkeerd; vanwege de single-threaded aard van Javascript heeft dit de voorkeur. Ik gooi dit er voor de volledigheid in, maar de vorige methode is efficiënter en past beter bij node.js, dus ga ervoor tenzij er een grote herschrijving bij betrokken is.

Het is niets waard dat beide gevallen afhankelijk zijn van asynchrone callbacks, wat betekent dat elke code daarbuiten mogelijk nog steeds kan worden uitgevoerd voordat andere zijn voltooid. Bijvoorbeeld door ons eerste fragment te gebruiken:

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

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

console.log("hello world");

Die laatste console.log wordt bijna gegarandeerd uitgevoerd voordat onze callback die is doorgegeven aan getStudentsData wordt geactiveerd. Tijdelijke oplossing? Ontwerp ervoor, het is gewoon hoe node.js werkt. In ons bovenstaande geval is het eenvoudig, we zouden console.log gewoon alleen . noemen in onze callback doorgegeven aan getStudentsData en niet daarbuiten. Andere scenario's vereisen oplossingen die iets meer afwijken van traditionele procedurele codering, maar als je er eenmaal je hoofd over hebt, zul je merken dat gebeurtenisgestuurd werken en niet-blokkeren eigenlijk een behoorlijk krachtige functie is.



  1. Mongo Triple Samengestelde Index

  2. MongoDB bevraagt ​​meerdere collecties tegelijk

  3. Communicatie tussen twee Docker-containers op macOS 10.12

  4. Wat is een TransientTransactionError in Mongoose (of MongoDB)?