私はあなたの質問であなたが提案したルートに行き、あなたのフェッチ関数にカスタムコールバックを添付します:
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に渡されたコールバックで、その外部ではありません。他のシナリオでは、従来の手続き型コーディングから少し離れたソリューションが必要ですが、頭を悩ませると、イベント駆動型であり、非ブロッキングが実際には非常に強力な機能であることがわかります。