Бих тръгнал по маршрута, който предлагате във вашия въпрос, и бих прикачал персонализирано обратно извикване към вашата функция за извличане:
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
});
Това е може би най-ефективният метод; като алтернатива можете да разчитате на стара школа while
цикъл, докато данните са готови:
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);
}
});
Използваме process.nextTick
вместо действително while
да се уверите, че други заявки не са блокирани междувременно; поради еднонишковия характер на Javascript това е предпочитаният начин. Включвам това с цел пълнота, но първият метод е по-ефективен и се вписва по-добре с node.js, така че го направете, освен ако не е включено сериозно пренаписване.
Нищо не струва, че и двата случая разчитат на асинхронни обратни извиквания, което означава, че всеки код извън него все още може потенциално да се изпълнява, преди другите да са готови. Например, използвайки първия ни фрагмент:
function getStudentsData(callback) {
//[...]
}
getStudentsData(function(dataList) {
//[...]
});
console.log("hello world");
Този последен console.log е почти гарантирано да работи, преди нашето обратно извикване да премине към getStudentsData да бъде задействано. Заобиколно решение? Проектирайте за него, просто така работи node.js. В нашия случай по-горе е лесно, просто ще извикаме console.log само в нашето обратно извикване се предава на getStudentsData, а не извън него. Други сценарии изискват решения, които се отклоняват малко повече от традиционното процедурно кодиране, но след като се запознаете с него, ще откриете, че управлението на събития и неблокирането всъщност е доста мощна функция.