1

I feel like this is really easy, but I can not figure it out.

I want to set the currentUserId inside of the getCurrentUser function, which I would like to be able to call inside other functions.

Below is what I have now, and it returns undefined. What am I missing?

var currentUserId;

function getCurrentUser()   {
    $.ajax({
        type: "GET",
        url: '/set_user',
        success: function(result)   {
            currentUserId = result.id;
            return currentUserId;
        },
        error: function(err)    {
            console.log(err);
        }

    })
};

getCurrentUser();
console.log("current user id is " + currentUserId);    
gwalshington
  • 1,418
  • 2
  • 30
  • 60
  • 3
    your console.log happens before the ajax has finished – naortor Oct 26 '16 at 15:47
  • @naortor you're exactly right -- i'm seeing this in my console. How do I solve this? The ultimate goal is to be able to call this function, and user the variable currentUserId in other functions – gwalshington Oct 26 '16 at 15:48
  • 1
    You can set `async: false` – Isukthar Oct 26 '16 at 15:49
  • 3
    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) – VLAZ Oct 26 '16 at 15:53
  • simply follow this link for precise example if you wanna make it synchronous http://stackoverflow.com/questions/133310/how-can-i-get-jquery-to-perform-a-synchronous-rather-than-asynchronous-ajax-re or use callback pattern to do something when response received – Pavneet_Singh Oct 26 '16 at 15:57
  • **Don't make it synchronous.** Refactor to work *with* async, not against it. If you need it sooner, then set it as part of the page render from the server-side (whatever tech is used, not stated in the question), or disable/hide page functionality/content until complete – freedomn-m Oct 26 '16 at 16:03

2 Answers2

2

This happens because inside getCurrentUser method you are doing an asynchronous AJAX call, so the value is not yet ready when you print it with console.log.

The value will be correctly set when the GET /set_user request will end successfully, only in that case the function:

    success: function(result)   {
        currentUserId = result.id;
        return currentUserId;
    }

will be executed and currentUserId will be set.

Based on jQuery.ajax() documentation, the value returned by $.ajax call is a Promise. So first, return the promise to the caller (1) and then wait the promise is resolved to print the value (2).

var currentUserId;

function getCurrentUser()   {
    return $.ajax({ // 1. Return the Promise here
        type: "GET",
        url: '/set_user',
        success: function(result)   {
            currentUserId = result.id;
            return currentUserId;
        },
        error: function(err)    {
            console.log(err);
        }

    })
};

// 2. Then wait the call to succeed before print the value (use the 'done' method)
getCurrentUser().done(function() {
  console.log("current user id is " + currentUserId);    
});
Andrea
  • 3,370
  • 1
  • 17
  • 25
  • I think this is the solution. I updated it, and I am now getting an error "cannot read property 'done' of undefined. Working through that error. Any thoughts as to what that issue is? Thanks! – gwalshington Oct 26 '16 at 16:07
  • Which version of jQuery are you using? Try to use `then` instead of `done`. – Andrea Oct 26 '16 at 16:12
  • .then doesn't work either. There is .done being used in the app already, so it's possible, but the whole function is coming back undefined. Jquery version: 1.11.3 – gwalshington Oct 26 '16 at 16:22
  • I could not find the difference between what I wrote to duplicate your answer, and your actual answer. So I copied and pasted, and voila. Something must have been a hair off. Thank you so much!! It works perfectly now. :) – gwalshington Oct 26 '16 at 16:26
2

Like Andrea explain, the value was not ready yet when you make a ajax call.

One way to avoid this is use callback:

function getCurrentUser(callback)   {
    $.ajax({
        type: "GET",
        url: '/set_user',
        success: function(result)   {
            var currentUserId = result.id;
            if (callback)
              callback(currentUserId);
        },
        error: function(err)    {
            console.log(err);
        }

    })
};

function displayResult(userId){
  console.log("current user id is " + userId);   
}

getCurrentUser(displayResult);

And this will also avoid the use of globe variable currentUserId.

Charles Guo
  • 140
  • 5