这部分是一个JavaScript技术问题。我试图建立一个对象,以Facebook id作为键,并以点赞数组作为值。我的问题是我最里面的函数,我无法访问设置键所需的变量fbid。
如何在内部匿名函数的范围内访问fbid?
friendsLikes = [];
FB.api('/me/friends',function(friends){
for(var i=0;i<friends.data.length;i++){
var fbid = friends.data[i].id
FB.api(fbid+'/likes',function(likes){
if(likes.data.length>=1){
//this is where I build the object
//I cannot use fbid for the key :(
console.log(likes.data.length);
}
})
}
})
最佳答案
问题在于,在执行回调之前,每次迭代都会更新fbid
。
循环浏览好友列表
将fbid
设置为朋友的ID
发起异步调用以获取该朋友的喜欢
继续下一个朋友,直到我们遍历整个列表
一段时间过去了
结果从服务器返回,并且回调开始执行。此时,fbid
对于所有回调都是相同的-具体来说,它被设置为列表中最后一个朋友的ID。
这是我捕获每次迭代的fbid
的方法:
friendsLikes = [];
FB.api('/me/friends',function(friends){
for(var i=0;i<friends.data.length;i++){
var fbid = friends.data[i].id
FB.api(fbid+'/likes', function(fbid) { return function(likes){
if(likes.data.length>=1){
// `fbid` will be correct here
console.log(likes.data.length);
}
}}(fbid));
}
});
注意,我们使用了一个自执行函数并传递了当前的
fbid
。这将返回一个在范围内具有正确的fbid
的函数。现在,请注意如何执行此操作:此代码的性能会很糟糕,因为您要为每个朋友支付一次HTTP往返费用。请记住,浏览器每个主机只能打开2-8个连接(取决于浏览器)之间的某个位置,所有这些调用都将进入graph.facebook.com。
适度的好友列表为200,往返时间为150ms,理论上最好的情况是大约4秒。如果浏览器仅进行2个并发连接,并且往返时间为200毫秒(即20秒),事情就会迅速恶化。
Facebook很有可能在某个时候限制您的访问速度。
相反,您需要使用Batch API。
FB.api('/', 'POST', { batch: [
{ method: 'GET', relative_url: id+'/likes' },
...
] }, function(r) {
// `r` will be an array of results for each item in `batch`
});