1

This is a noob JS question that I can't quite verbalize well enough to successfully Google.

function getUser(username){
    var toReturn = { };
    Restangular.one('users', username).get().then(function(result){ 
        toReturn = result;   
    });        
return toReturn //doesn't work 
}

Restangular.one(...).get() initializes a REST call to get user data from the server. .then(...) is a callback that runs after data is returned. However, this getUser() function, as written, always returns an empty object, because it returns before the callback is triggered. How might I go about writing this function so that it returns the retrieved object?

(p.s. I know that this question is academic with regard to angular, since it handles promise resolutions transparently. I'm new to JS in general, and this is a general JS question).

drew moore
  • 31,565
  • 17
  • 75
  • 112
  • Is your callback asynchronously called ? – Sebastien C. Apr 09 '14 at 07:37
  • Have a look at how to deal with async functions without promises http://stackoverflow.com/questions/22948415/how-to-deal-with-asynchronous-functions-without-promises/22949279#22949279 – shanks Apr 09 '14 at 07:38

6 Answers6

1

Since server call is asynchronous, you should provide callback.

You can use promise or callback

Using Callback

 function getUser(username, callback){

    Restangular.one('users', username).get().then(function(result){ 
        callback(result);   
    });        
 }

call: getUser('username', function(result){ /*do stuff here */ });

Using Promise

 function getUser(username){
    var callback;
    var promise = {then: function(cb){
         callback = cb;
      }
    };
    Restangular.one('users', username).get().then(function(result){ 
        callback(result);   
    }); 
   return promise;       
 }

call: getUser('username').then(function(result){ /*do stuff here */ });)

Anoop
  • 23,044
  • 10
  • 62
  • 76
0

Just try with:

function getUser(username, callback){
    Restangular.one('users', username).get().then(callback);
}

getUser('hsz', function(result){ 
    console.log(result); 
});
hsz
  • 148,279
  • 62
  • 259
  • 315
0

The rest call is probably an async call. If you have control over the API, you can make a synchronous request which will then wait for it to return. Something like this:

function getUser(username){
    var toReturn = { };
    return Restangular.one('users', username).get().then(function(result){ 
        return result;   
    });
}

It depends on how then is handled too. I'm assuming here that then() will return the result as well.

However, the best way in this scneario is to use a callback:

function getUser(username, callback) {
    Restangular.one('users', username).get().then(callback);
}
Nick
  • 4,002
  • 4
  • 30
  • 41
0

Yes, that won't work because the problem is with your function. Every AJAX call is executed asynchronously, thus like the result.

If you have made an AJAX call like that, it will have to ask the browser to load that request, process the response and then execute the (function(result) { }) that you put as the last argument with the result.

So, you must change your function to have a callback too, like:

function getUser(username, onResultHandler){
    Restangular.one('users', username).get().then(onResultHandler);        
}

Then you can use it like this:

getUser('Daniel', function(user) { updateSomethingWithMyUser(user); });

Did you get it?

0

The simplest way, is to not overwrite the object you just created, because objects are passed around by reference.

For example:

var a = function() { 
     var b = {}; 
     setTimeout(function() { b.a = 'hi'; }, 100); 
     return b; 
}

b = a();
console.log(b); // Object {}
setTimeout(function() { console.log(b) }, 100); // Object {a: "hi"}

Because we simply set a property of the object, we are setting a property on the SAME object that got returned. When you do something like:

toReturn = result;   

like in your function, you aren't changing the thing toReturn referenced, you are changing what toReturn references to (it used to reference to {}, now it references whatever result it).

So, in your case:

function getUser(username){
  var toReturn = { };
  Restangular.one('users', username).get().then(function(result){ 
    toReturn.result = result;   
  });        
  return toReturn;
}

As soon as you get the result, toReturn.result will have it.

dave
  • 62,300
  • 5
  • 72
  • 93
0

How might I go about writing this function so that it returns the retrieved object?

You can't, and you shouldn't. Restangular makes the call async so that your application can carry on running while waiting for a response.

If you want to make it look synchronous, I suggest the following approach (here's where its different from other answers):

function getUser(username){
    return Restangular.one('users', username).get();
}

/* Usage */

getUser('username')
.then(function(result) {
    /* do something with result */ 
});
Nathan Kot
  • 2,392
  • 1
  • 21
  • 31