Tôi sẽ đi theo con đường bạn đề xuất trong câu hỏi của bạn và đính kèm một lệnh gọi lại tùy chỉnh vào chức năng tìm nạp của bạ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
});
Đó có lẽ là phương pháp hiệu quả nhất; hoặc bạn có thể dựa vào trường cũ while
lặp lại cho đến khi dữ liệu sẵn sàng:
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);
}
});
Chúng tôi sử dụng process.nextTick
thay vì một while
thực tế để đảm bảo các yêu cầu khác không bị chặn trong thời gian chờ đợi; do tính chất đơn luồng của Javascript nên đây là cách được ưu tiên. Tôi đang ném nó vào vì mục đích hoàn chỉnh, nhưng phương pháp cũ hiệu quả hơn và phù hợp hơn với node.js, vì vậy hãy sử dụng nó trừ khi có liên quan đến việc viết lại lớn.
Không có giá trị gì khi cả hai trường hợp đều dựa vào lệnh gọi lại không đồng bộ, có nghĩa là bất kỳ mã nào bên ngoài nó vẫn có thể chạy trước khi những mã khác được thực hiện. Ví dụ:sử dụng đoạn mã đầu tiên của chúng tôi:
function getStudentsData(callback) {
//[...]
}
getStudentsData(function(dataList) {
//[...]
});
console.log("hello world");
Console.log cuối cùng đó gần như được đảm bảo chạy trước khi lệnh gọi lại của chúng tôi được chuyển tới getStudentsData được kích hoạt. Cách giải quyết? Thiết kế cho nó, đó chỉ là cách node.js hoạt động. Trong trường hợp của chúng tôi ở trên, thật dễ dàng, chúng tôi chỉ gọi console.log only trong lệnh gọi lại của chúng tôi được chuyển tới getStudentsData chứ không phải bên ngoài nó. Các tình huống khác yêu cầu các giải pháp khác nhiều hơn một chút so với mã hóa thủ tục truyền thống, nhưng khi bạn hiểu rõ về nó, bạn sẽ thấy tính năng hướng sự kiện và không chặn thực sự là một tính năng khá mạnh mẽ.