这部分是一个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`
});

10-06 04:20