0

I'm trying to get the URL (str variable) using FB API.

When I tried CONSOLE2 console.log(str) it showed the exact value of str variable which contains URL for photo.

But when I tried CONSOLE1 it didn't work. It printed nothing.

Is it because of some async functions? If yes, how can write the code that following two statements (see Note 1) work (it doesn't matter one executes after another, I just want the URL in CONSOLE1 where I have called getPhoto())

Note 1: Both statements mean the location.href and CONSOLE1, to ensure that I'm getting the value of str inside the Login() function.

  function Login()
  {         
    FB.login(function(response) {
       if (response.authResponse) 
       {
          getPhoto();
         // window.location.href="quiz.html";
          //**CONSOLE1** 
          console.log(str);
         } else 
        {
           console.log('User cancelled login or did not fully authorize.');
        }
     },{scope: 'email,user_photos,user_videos,publish_actions'});
  }

  function getPhoto()
  {
    FB.api('/me/picture?type=normal', function(response) {
      var str="<br/><b>Pic</b> : <img src='"+response.data.url+"'/>";
        document.getElementById("status").innerHTML+=str;
         //**CONSOLE2**
         console.log(str);     
    });
  }
Vikas Kumar
  • 689
  • 3
  • 7
  • 18
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – CBroe Nov 28 '16 at 11:41

3 Answers3

1

How about this:

function Login() {       
    FB.login((response) => {
        if (response.authResponse) {
            getPhoto((str) => {
                console.log(str);
            });
        } else {
            console.log('User cancelled login or did not fully authorize.');
        }
    },{scope: 'email,user_photos,user_videos,publish_actions'});
}

function getPhoto(callback) {
    FB.api('/me/picture?type=normal', (response) => {
        const str = '<br/><b>Pic</b> : <img src="' + response.data.url + '"/>';
        document.getElementById('status').innerHTML += str;
        callback(str);     
    });
}

There are other solutions too (for example, with Promises), but using a callback function is very easy. I also added ES6 syntax (const, arrow functions).

You can also use FB.getLoginStatus to check if the user is logged in on page load, and call getPhoto in the callback of that function too.

For example: http://www.devils-heaven.com/facebook-javascript-sdk-login/

andyrandy
  • 72,880
  • 8
  • 113
  • 130
  • I quite didn't understand arrow thing. Could you please make it work without using arrow thing? – Vikas Kumar Nov 28 '16 at 10:19
  • just replace this: "(response) => {" with this: "function (response) {" ...or better, learn ES6, it´s about time ;) – andyrandy Nov 28 '16 at 10:21
  • I tried to understand this callback thing by this example: http://stackoverflow.com/questions/40842335/how-do-i-use-callback-to-access-this-variable but it didn't work. Could you please answer there so I can understand this thing? – Vikas Kumar Nov 28 '16 at 10:44
  • if you don´t know what a callback function is, or what asynchronous means, you should learn the basics of javascript before dealing with the facebook api. those are free and pretty good, for example: https://github.com/getify/You-Dont-Know-JS – andyrandy Nov 28 '16 at 10:59
  • Thank you :) One more general question. I'm working with JavaScript since 1 year. I've used it in my practice projects. I've used it with jQuery and Ajax as well. I know about callbacks like callbacks in jQuery hide() or show() methods and especially callbacks like this: https://www.tutorialspoint.com/nodejs/nodejs_callbacks_concept.htm The thing is I have worked with callbacks but still I don't understand the thing you have used and the example I've tried in above mentioned question. SO THE QUESTION IS: If someone asks me: Do you know JavaScript? How should I reply? – Vikas Kumar Nov 28 '16 at 11:10
  • 1
    if you don´t know exactly how callbacks/async works, then you don´t know javascript, i´m afraid ;) tip: learn vanilla javascript, you really don´t need jquery and you should learn the basics before using any library. – andyrandy Nov 28 '16 at 11:58
0

In the CONSOLE2 block, you explicitly define the variable str:

var str=...

But in CONSOLE1 block, you never actually define the variable. When the function getPhoto terminates, the variable str goes out of scope and no longer exists.

To fix it, put your logic inside the callback function on the FB.api call. You can place that call inside the FB.login callback function rather than in its own function. Like this:

FB.login(function(response) {
  if (response.authResponse) {
    FB.api('/me/picture?type=normal', function(response) {
...

In javascript, you have to chain or nest your callbacks. You have to wait for the login callback, then make the next API call, then make your get picture callback, etc.

fullstackdev
  • 1
  • 1
  • 2
  • putting FB.api inside the FB.login callback instead of a separate function is not a good idea, what if you want to call that function again later, or on page load? – andyrandy Nov 28 '16 at 08:46
  • If you actually DO want to do that you can always refactor. No point in making things more complicated when the guy asking the question doesn't understand scoping. Returning a value from another function requires a callback. I gave him the simplest possible answer. – fullstackdev Dec 02 '16 at 23:18
  • Specifically, look at his comments on the other answer: "I quite didn't understand arrow thing. Could you please make it work without using arrow thing?" I felt the answer I gave was commensurate with his understanding of JS and specifically addressed his problem. – fullstackdev Dec 04 '16 at 10:54
0

The scope of str var remains inside the getPhoto function. For getting value in CONSOLE1 you need to do return value of str from getPhoto function.

Hope this helps you.

Amit Jamwal
  • 629
  • 1
  • 6
  • 16