以下の実装をご覧ください。私はそれを複数の機能に分割して、各ステップを分離しました。ループとコールバックを処理する場合、無名関数が定義されているスコープを追跡することが非常に重要になります。
理論的には、書いていたように1つのライナーですべてを行うことができます...
...しかし、ネストされたコールバックにさらに進むと、非常に混乱します。
1つの解決策は、各関数内のすべての変数を100%グローバルにすることi
です。これにより、囲まれた参照のみが必要になります。しかし、それは本当にきれいではありません。
各関数を調べて、各ステップが呼び出す関数(またはコールバックのクロージャ)にどのパラメーターが入っているかをメモします。それらはすべて必要です(この方法で分離するか、ワンライナーのクロージャーなどで分離するかは関係ありません)。
以下は、Facebook開発者サンドボックス内で(初めてAPIを使用して)私にとっては問題なく機能しました。
ログは、データがどのように出力されているかを確認し、基本的なスタックトレースを保持するためのものでした。
var userList = [],
userCount = 0;
function getfriends () {
//console.log("getFriends");
var url = "/me/friends";
FB.api(url, function (response) {
if (response.error && response.error.message) { return false; }
userList = userList.concat(response.data);
userCount = response.data.length;
compareAllFriends();
});
}
function compareAllFriends () {
//console.log("compareAllFriends");
var i = 0, l = userCount, userID;
for (; i < l; i += 1) {
userID = userList[i].id;
compareFriendsWith (i, userID);
}
}
function compareFriendsWith (i, id) {
//console.log("compareFriendsWith", i, id);
var path = "/me/mutualfriends/",
url = path + id + "/";
FB.api(url, (function (i) {
return function (response) {
//console.log(i, response);
var numFriends = (response.data) ? response.data.length : 0;
setMutualFriends(i, numFriends);
userCount -= 1;
//console.log(userCount);
if (userCount === 0) {
display_results();
//console.log("DISPLAYING");
}
};
}(i)));
}
function setMutualFriends (i, friendcount) { userList[i].mfCount = friendcount; }