vorrei andare via lei suggerisce nella tua domanda e allegare un callback personalizzato alla funzione recupero:
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
});
Questo è probabilmente il metodo più efficiente; in alternativa si può fare affidamento su una vecchia scuola while
ciclo fino a quando i dati sono pronti:
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);
}
});
Usiamo process.nextTick
invece di un vero e proprio while
per assicurarsi che altre richieste non sono bloccate nel frattempo; a causa della natura a thread singolo di Javascript questo è il modo preferito. Lo sto lanciando per completezza, ma il precedente metodo è più efficiente e si adatta meglio con node.js, quindi provatelo a meno che non sia coinvolta una riscrittura importante.
Non vale nulla che entrambi i casi si basino su richiami asincroni, il che significa che qualsiasi codice al di fuori di esso può ancora essere eseguito prima che altri vengano eseguiti. Per esempio, utilizzando il nostro primo frammento:
function getStudentsData(callback) {
//[...]
}
getStudentsData(function(dataList) {
//[...]
});
console.log("hello world");
Quell'ultima console.log è quasi garantito per funzionare prima del nostro passato al callback getStudentsData viene licenziato. Soluzione? Progetta per questo, è come funziona node.js. Nel nostro caso sopra è facile, dovremmo chiamare console.log solo nel nostro callback passato a getStudentsData e non al di fuori di esso. Altri scenari richiedono soluzioni che si discostano un po 'di più dalla codifica procedurale tradizionale, ma una volta che ci si capisce da capo si scoprirà che essere guidati dagli eventi e non bloccanti è in realtà una caratteristica piuttosto potente.
Primo esempio non sembra funzionare per me :(Vedere [questo] (https://i.gyazo.com/129b071f39bbd1a1c491638be634b00c.png), la chiamata Redis è asincrona Il. il log della console dei miei 'risultati' verrebbe mostrato per primo poiché è la stessa logica dell'esempio, hmmm –