0

I've read just about every post on Stack Overflow and elsewhere regarding this issue, but nothing seems to work. I need to retrieve a user's credits before they're allowed to make a purchase. Everything seemed to be working until earlier. Here's the code I thought was working:

function getCredits() {
    return $.getJSON('users/getCredits').done(function(resp) {
                return parseInt(resp.credits);
          });
}

When I found this wasn't working as expected I tried setting an outer variable which .done() would modify.

function getCredits() {
    var active_credits;
    $.getJSON('users/getCredits')) 
        .done(function(resp) {
            active_credits = parseInt(resp.credits);
        });

     return active_credits;
}

I've also tried playing around with .when() and .then() methods, which I have little familiarity with.

function getCredits() {
    $.when($.getJSON('users/getCredits')) 
    .then(function(resp) {
        active_credits = parseInt(resp.credits);
    });
 }

The only thing I've found to work is using $.ajax() with the async option set to false. But with that I get a deprecation warning, plus I've read several posts warning of this being bad practice.

Any help with this would be appreciated. My assumption about .done() has always been it waits until the HTTP request is finished processing.

UPDATE

So here's my latest attempt. I'm passing in a callback as has been suggested in this post as well as other posts. But I'm still getting an undefined message when trying to read the method's return value. I'm not sure what I'm doing wrong.

function getCredits() {
   var active_credits;

   function requestCredits(callback) {
     $.getJSON('users/getCredits', callback).done(function(resp) {
       callback(resp);
     });
   }

   requestCredits(function(resp) {
     active_credits = parseInt(resp.credits);
   });

   return active_credits;
}

I've also tried returning the value returned by the callback.. with no luck.

 function getCredits() {
       var active_credits;

       function requestCredits(callback) {
         $.getJSON('users/getCredits', callback).done(function(resp) {
           callback(resp);
         });
       }

      return requestCredits(function(resp) {
         return parseInt(resp.credits);
       });
    }
Brandon Buster
  • 77
  • 2
  • 10
  • This happened to me too... Have you tried adding a delay to your promise? – snowYetis Apr 01 '15 at 20:07
  • 2
    Your `return` in `getCredits` will not wait for an async function to complete, it returns instantly and your getJSON result gets lost. You'll need to take the functionality that relies on the getCredit result and fire it either in the promise or as another promise/callback. – Jesse Kernaghan Apr 01 '15 at 20:11
  • How are you using `getCredits()` in the rest of your code? – Jack Apr 01 '15 at 20:13
  • I have a bad news for you. This happens to me before. You need to stop using AJAX in a separate functions and expect it to return. You will need to modify the architecture of your code. To simply this for you, let's say the function execution will take 1 sec, and the ajax will take 3 sec, the function will return whatever it has in 1 sec, which is false, or null, since there were no values to return. No matter what, the function execution will be faster than the ajax. – Mohammed Joraid Apr 01 '15 at 20:25

1 Answers1

3

If you are doing something like this var credits = getCredits(); The rest of your code will continue to execute and credits won't be what you expect it to be.

The least complex solution would be to ditch getCredits() and just use the getJson call directly. Something like the below code.

$.getJSON('users/getCredits').done(function(resp) {
    var credits = resp.credits;

    //the rest of your code that depends on credits.
});

If you want to keep getCredits() you can do something like this. You're always going to have to have a callback, that's just the nature of async in javascript. This is entirely off the top of my head.

function getCredits() {
    return $.getJSON('users/getCredits');
}

//some other code that uses getCredits()
getCredits().done(function(resp){
  var credits = resp.credits;

  //the rest of your code that depends on credits.
});
Jack
  • 8,851
  • 3
  • 21
  • 26
  • I would vote up for the second option as it allows to modification/editing etc of the returned result before it get's returned which helps in separating the concerns and makes it work as a complete block of code. Having to do a callback is just a matter of habit, with time it will look normal or even as a must. – Mohammed Joraid Apr 01 '15 at 20:53
  • @Joraid There's several ways to do this. I just wanted to help solve the problem while keeping it accessible to someone new to async methods in javascript. – Jack Apr 01 '15 at 20:57
  • Thanks for the suggestion, Jack. I've done as you've described and I've read the related links provided by others but the fix is still elusive. – Brandon Buster Apr 02 '15 at 23:17