Jeg ville gå den vej, du foreslår i dit spørgsmål, og vedhæfte et tilpasset tilbagekald til din hentefunktion:
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
});
Det er nok den mest effektive metode; alternativt kan du stole på en gammel skole while
sløjfe, indtil dataene er klar:
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);
}
});
Vi bruger process.nextTick
i stedet for en faktisk while
for at sikre, at andre anmodninger ikke blokeres i mellemtiden; på grund af Javascripts enkelttrådede karakter er dette den foretrukne måde. Jeg smider dette ind for fuldstændighedens skyld, men førstnævnte metode er mere effektiv og passer bedre til node.js, så gå efter det, medmindre en større omskrivning er involveret.
Det er intet værd, at begge tilfælde er afhængige af asynkrone tilbagekald, hvilket betyder, at enhver kode udenfor den stadig potentielt kan køre, før andre er færdige. Brug f.eks. vores første kodestykke:
function getStudentsData(callback) {
//[...]
}
getStudentsData(function(dataList) {
//[...]
});
console.log("hello world");
Den sidste console.log er næsten garanteret til at køre, før vores tilbagekald videregives til getStudentsData bliver fyret. Løsning? Design til det, det er bare sådan node.js fungerer. I vores tilfælde ovenfor er det nemt, vi ville bare kalde console.log kun i vores tilbagekald gået til getStudentsData og ikke uden for det. Andre scenarier kræver løsninger, der afviger en smule mere fra traditionel proceduremæssig kodning, men når du først har fået styr på det, vil du opdage, at det at være hændelsesdrevet og ikke-blokerende faktisk er en ret kraftfuld funktion.