2

In this example from Angularjs Docs there is some *magic*, which i can't figure out. Here is a code:

var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
  user.abc = true;
  user.$save();
});

And one thing confusing me - how we can refer to user object inside callback and get retrieved data, when it is necessary to populate user first. But to do so value should be returned from User.get().

Like that:

call User.get() → return from User.get() → call function() callback

But after return it is not possible to execute anything, right?

4
  • No magic here, user is populated by the call to get, callback happens later - user is accessible in the callback through closure scope. Commented Oct 16, 2014 at 19:05
  • You´re right, but do you know what User.get will return? seems an object to me. If that´s the case, when the callback is executed will get the abc property. Callback can be deliberately be called at any point of the code.. Commented Oct 16, 2014 at 19:06
  • 1
    @Guillermo. user does appear to be an object. When the callback occurs it either changes the value or creates the abc property of the user object. Commented Oct 16, 2014 at 19:09
  • 2
    Really Grisha - to understand this code you have to do a little reading up on asynchronous coding and JavaScript closure scope. As someone who used to be a C# developer its a little odd a first, but you'll get the hang of it. Commented Oct 16, 2014 at 19:10

2 Answers 2

1

It is absolutely possible to return the user and still have not executed the callback, and this is what this code example is showing.

The implementation of User.get might be something like:

User.prototype.get = function(parameters, callback) {
  var user = {
     abc: false
  }

  // do other stuff to construct the object

  someLongAsyncOperation(callback);

  return user;
}

Here the user is returned, but there is still a callback to be completed. Then within that callback the user can be accessed via closure scope. someLongAsyncOperation could be anything that later calls callback, you could try it out yourself with something as simple as a setTimeout or Angular's $timeout.

Its not in my opinion a great pattern, and it might be better to include the created user as a parameter in the callback - but it would work.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Did not imagine that callback function could be passed to some other place and invoked later, and living time of User.get() != living time of callback reference.
But here we encounter promises, because User.get() should terminate quickly, that is registering on some network events. But it is not possible to get reference to user object itself and User.get() returns "transforming" object, promise i guess.
0
  1. User.get() returns a blank object and performs an async GET to /user/123. This empty object is assigned to the user variable in the function scope.
  2. The rest of the function (if there is any) executes and the function returns.
  3. When the async call returns, the get() method populates the existing blank object's properties with the properties of the object returned, so the user variable now has the results of the callback.
  4. The get() method calls the callback you specify. It has access to the function's user variable that is now populated from the async call.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.