Šel bych cestou, kterou navrhujete ve své otázce, a připojil bych k vaší funkci načítání vlastní zpětné volání:
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
});
To je pravděpodobně nejúčinnější metoda; alternativně se můžete spolehnout na starou školu while
smyčky, dokud nebudou data připravena:
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);
}
});
Používáme process.nextTick
místo skutečného while
zajistit, aby mezitím nebyly zablokovány další požadavky; kvůli jednovláknové povaze Javascriptu je to preferovaný způsob. Uvádím to pro úplnost, ale předchozí metoda je efektivnější a lépe se hodí k node.js, takže do toho jděte, pokud nejde o zásadní přepis.
Nestojí za nic, že oba případy se spoléhají na asynchronní zpětná volání, což znamená, že jakýkoli kód mimo něj může stále potenciálně běžet dříve, než budou provedeny ostatní. Např. pomocí našeho prvního úryvku:
function getStudentsData(callback) {
//[...]
}
getStudentsData(function(dataList) {
//[...]
});
console.log("hello world");
Je téměř zaručeno, že se tento poslední soubor console.log spustí, než bude spuštěno naše zpětné volání předané na getStudentsData. Řešení? Design pro to, node.js prostě funguje. V našem případě výše je to snadné, zavolali bychom pouze console.log pouze v našem zpětném volání předáno getStudentsData a ne mimo něj. Jiné scénáře vyžadují řešení, která se trochu více odchylují od tradičního procedurálního kódování, ale jakmile si to uvědomíte, zjistíte, že řízená událostmi a neblokování je ve skutečnosti docela výkonná funkce.