Как построить объект из друзей и лайков - PullRequest
1 голос
/ 12 марта 2012

Это частично вопрос техники javascript.Я пытаюсь создать объект с идентификатором facebook в качестве ключа и массивом лайков в качестве значения.Моя проблема заключается в моей самой внутренней функции, я не могу получить доступ к переменной 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);
            }
        })
    }
})

1 Ответ

4 голосов
/ 12 марта 2012

Проблема в том, что fbid обновляется на каждой итерации перед выполнением обратного вызова.

  • Перебрать список друзей
  • Установите fbid для идентификатора друга
  • Инициируйте асинхронный вызов, чтобы получить лайки этого друга
  • Переходите к следующему другу, пока мы не пройдемся по всему списку
  • проходит некоторое время
  • Результаты возвращаются с сервера, и начинают выполняться обратные вызовы. На этом этапе fbid одинаково для всех обратных вызовов & ndash; в частности, для него задан идентификатор последнего друга в списке.

Вот как я собираю 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 и большом времени в оба конца 150 мс теоретический сценарий в лучшем случае составляет ~ 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`
});
...