15

Nie mam żadnych problemów z logowaniem się, a nawet wywoływaniem api, po prostu mam problem z uzyskaniem odpowiedzi poza wywołaniem api. Wiem, że działa asynchronicznie, więc chciałbym umieścić go w funkcji, która zwróci odpowiedź. Oto mój pomysłJak korzystać z odpowiedzi FB.api (JS SDK) poza funkcją zwrotną?

//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; 
} 

Chciałbym wezwać mnie funkcji/API raz na początku, a następnie przekazać go wokół moich widoków obiektów (wystarczy użyć odpowiedź wewnątrz szkieletu Obejrzane) oraz w zależności od tego, co jest potrzebne są inne wywołania api. Obecnie mam pewne rzeczy działa poprzez wywołanie widoku od wewnątrz zwrotnego

//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}); 
    }); 

I orginally starał, ale ponieważ wywołanie API jest asynchroniczny miałem problemy z rzeczy jest niezdefiniowany

//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 

I tracę pierwszą odpowiedź, kiedy robię drugą. Na przykład moje pierwsze wywołanie api to/me, aby uzyskać informacje o użytkowniku. Mogę wtedy zadzwonić/twoje-fb-id/zdjęcia i uzyskać zdjęcia, ale jeśli wykonam połączenie z inną funkcją wewnątrz wywołania funkcji Photo Api, mogę tylko odwołać się do tej odpowiedzi, straciłem odpowiedź original/me. Gdybym mógł uzyskać odpowiedź z callbacku, byłbym w stanie przekazać go w razie potrzeby. Rozumiem, że odpowiedź jest poprawna tylko wewnątrz wywołania zwrotnego, więc jak mogę uczynić ją ważną poza wywołaniem zwrotnym, biorąc pod uwagę jej asynchroniczność?

Odpowiedz

24

OK, wszyscy to wymyślili. Zajęło mi to dużo czasu i przeczytałem wiele różnych stron. To co powiedziałem, chciałem zrobić wszystkie transakcje z callbackami i zamknięciami. Najpierw omówię problem z oddzwanianiem. Ponieważ funkcja FB.api jest asynchroniczna, nigdy nie wiadomo, kiedy powróci. Możesz zatrzymać JavaScript lub ustawić timer, ale jest to okropny sposób na zrobienie tego. Potrzebujesz połączenia zwrotnego. W rzeczywistości FB.api używa wywołania zwrotnego. Taka jest funkcja anonimowa jako drugi parametr. To, co zrobiłem, to stworzyłem inną funkcję, która nazywała się fbUser i używała wywołania zwrotnego. Oto co zrobiłem:

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

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

Uruchomienie Funkcja ta wywoływana jest na pozytywnej odpowiedzi Auth na Facebooku. Następnie wywołuje funkcję fbUser, która ma wywołanie zwrotne. Wywołanie zwrotne zwraca wywołanie zwrotne z funkcji FB.api. Ponieważ startThis używa tego wywołania zwrotnego z zwracaną wartością, która jest nazywana modelem, drugi kod nie zostanie wykonany, dopóki nie zostanie zwrócone wywołanie zwrotne. Nigdy więcej niezdefiniowanych problemów. Te funkcje są tylko opakowaniami, aby uzyskać odpowiedź Facebooka na moje widoki. Mogłem dodać jedną zbyt wiele warstw abstrakcji, ale jeśli chcesz przekazać odpowiedź, tak właśnie jest.

Po drugie chciałem przekazać tę odpowiedź do innego widoku. Na przykład jeden widok ładuje podstawowe informacje (używając odpowiedzi z fbUser). Teraz chcę przekazać to do innego widoku, który ładuje zdjęcia (wiem, że to nie jest najlepsza praktyka MVC, ale używając Facebooka nie mam zbytniej kontroli nad Modelem). Problem polegał na tym, że nie mogłem przekazać oryginalnej odpowiedzi do następnego widoku, ponieważ wewnątrz funkcji wywołania zwrotnego dla wywołania FB.api this odnosi się do Window, a nie do obiektu, w którym się znajdowałem. Rozwiązanie: zamknięcia. Nie wyjaśniam tego doskonale, ale zamknięcie jest lokalną zmienną wewnątrz funkcji, która wciąż ma odniesienie wewnątrz anonimowej funkcji. Oto moje rozwiązanie, które powinny ilustrować to, co mówię:

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

Funkcja loadPhoto jest opakowaniem załadować Zobacz zdjęcie (wiem kręgosłup może mi pomóc z załadowaniem różne poglądy, ale byłem walce jeden problem w czas). Wymaga wywołania photo api jako modelu, liczby jako przesunięcia i odpowiedzi origanl. Pierwszy wiersz tej funkcji ustawia tę zmienną lokalną This.To pozwala mi wewnątrz anonimowej funkcji oddzwaniania odwoływać się do obiektu, z którego został wywołany.

Mam nadzieję, że to może pomóc komuś, ponieważ spędziłem wiele godzin i dużo czasu na testowanie, aby znaleźć rozwiązanie tego problemu. Jeśli nie wiesz, jak działają wywołania zwrotne lub zamknięcia, trudno znaleźć informacje, których szukasz.

+0

Dziękujemy! Pomogło mi to w dokładnie tej samej sytuacji! –

Powiązane problemy