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.