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

У меня нет проблем с входом в систему или даже вызовом 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;
}

Я хотел бы вызвать функцию /me api один раз в начале, а затем передать ее моим объектам представления (я просто использую ответ внутри 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 был асинхронным, у меня были проблемы с вещами undefined

//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 и получить фотографии, но если я сделаю вызов другой функции внутри обратного вызова api фотографии, я могу только ссылаться на этот ответ, я потерял исходный/ответ. Если бы я мог получить ответ из обратного вызова, я бы смог передать его по мере необходимости. Я понимаю, что ответ действителен только внутри обратного вызова, так как я могу сделать его действительным вне обратного вызова, принимая во внимание его асинхронность?

Ответы

Ответ 1

ОК, я все понял. Мне потребовалось много времени и я читал много разных страниц. Я сказал, что хочу делать все сделки с обратными вызовами и закрытием. Сначала я расскажу о проблеме обратного вызова. Поскольку функция 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 использует этот обратный вызов с возвращаемым значением, которое называется моделью, другой код не будет выполняться до тех пор, пока обратный вызов не вернется. Больше проблем undefined. Эти функции - только обертки, чтобы получить ответ 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 фотографии как модель, число как смещение и ответ origanl. Первая строка этой функции устанавливает эту локальную переменную This. Это позволяет мне внутри анонимной функции обратного вызова ссылаться на объект, из которого он был вызван.

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