Как использовать ответ FB.api (JS SDK) вне функции обратного вызова? - PullRequest
15 голосов
/ 04 октября 2011

У меня нет проблем со входом в систему или даже с вызовом API, у меня просто проблема с получением ответа вне функции обратного вызова API.Я знаю, что он работает асинхронно, поэтому я хотел бы поместить его в функцию, которая будет возвращать ответ.Вот моя идея

//What I would like to be able to do
function fbUser(){
   FB.api('/me', function(response){
      //this logs the correct object
      console.log(response);
   });
//How do I get the response out here?
return response;
}

Я хотел бы вызвать функцию api / me один раз в начале, а затем передать ее своим объектам вида (я просто использую ответ внутри Backbone Views) и в зависимости отчто нужно сделать другие вызовы API.В настоящее время у меня есть определенные вещи, работающие, вызывая представление изнутри обратного вызова

//What I am doing now, but I lose the ability to pass anything other than the 
//the current response to this function/View
FB.api('/me', function(response){
     var newView = new facebookView({model: response});
   });

Я первоначально пытался это сделать, но из-за асинхронного вызова API у меня были проблемы с неопределенными вещами

//What I started with but had async issues
var fbResponse;
FB.api('/me', function(response){
     fbResponse = response;
   });
//I would then try and use fbResponse but it would be undefined

Я теряю первый ответ, когда делаю второй.Например, мой первый вызов API - это / me, чтобы получить информацию о пользователе.Затем я могу позвонить / your-fb-id / photos и получить фотографии, но если я сделаю вызов другой функции внутри функции обратного вызова photo api, я могу ссылаться только на тот ответ, который потерял исходный ответ / me.Если бы я мог получить ответ от обратного вызова, то я мог бы передать его по мере необходимости.Я понимаю, что ответ действителен только внутри обратного вызова, так как мне сделать его действительным вне обратного вызова, учитывая его асинхронность?

1 Ответ

24 голосов
/ 05 октября 2011

ОК, все, я понял это.Это заняло у меня много времени и чтение разных страниц.То, что я сказал, я хотел сделать все сделки с обратными вызовами и замыканиями.Сначала я расскажу о проблеме с обратным вызовом.Поскольку функция FB.api является асинхронной, вы никогда не знаете, когда она вернется.Вы можете остановить Javascript или установить таймер, но это ужасный способ сделать это.Вам нужен обратный звонок.На самом деле FB.api использует обратный вызов.Это то, что анонимная функция в качестве второго параметра.То, что я сделал, было создать другую функцию, которая называется fbUser и использует обратный вызов.Вот что я сделал:

function startThis() {  
    var getUser = fbUser(function(model){
        console.log(model);
        startapp(model);
    }); 
};

function fbUser(callback){  
        FB.api('/me', function(response){
                callback(response);
            });
}

Функция startThis вызывается при положительном ответе аутентификации Facebook.Затем он вызывает функцию fbUser, которая имеет обратный вызов.Обратный вызов возвращает обратный вызов из функции FB.api.Поскольку startThis использует этот обратный вызов с возвращаемым значением, называемым моделью, другой код не будет выполняться, пока обратный вызов не вернется.Нет больше неопределенных проблем.Эти функции являются просто обертками, чтобы получить ответ Facebook на мои взгляды.Возможно, я добавил слишком много слоев абстракции, но если вы хотите передать ответ, то это путь.

Во-вторых, я хотел передать этот ответ другому представлению.Например, одно представление загружает основную информацию (используя ответ от fbUser).Теперь я хочу передать это другому представлению, которое загружает фотографии (я знаю, что это не лучшая практика MVC, но с помощью Facebook я не контролирую модель).Однако проблема, с которой я столкнулся, заключалась в том, что я не смог передать исходный ответ следующему представлению, поскольку внутри функции обратного вызова для вызова FB.api this ссылается на Window, а не на объект, в котором я находился. Решение: замыкания,Я не буду объяснять это полностью, но замыкание - это локальная переменная внутри функции, которая все еще имеет ссылку внутри анонимной функции.Вот мое решение, которое должно проиллюстрировать то, о чем я говорю:

photos: function(){
            var This = this;
            var apiString = '/' + this.model.id + '/photos';
            FB.api(apiString, function(response){
                loadPhoto(response,  1, This.model);
            });

Функция loadPhoto - это обертка для загрузки вида фотографии (я знаю, что магистраль может помочь мне с загрузкой разных видов, но я справилась с однимпроблема за один раз).Он принимает вызов фото api в качестве модели, номер в качестве смещения и исходный ответ.Первая строка в этой функции устанавливает это в локальную переменную This.Это позволяет мне внутри анонимной функции обратного вызова ссылаться на объект, из которого он был вызван.

Я надеюсь, что это может кому-то помочь, поскольку я потратил много часов и много времени на тестирование, чтобы найти решение этой проблемы.Если вы не знаете, как работают обратные вызовы или замыкания, трудно найти искомую информацию.

...