2

The following dummy controller in Coffeescript:

GlobalTimelineController = ($scope, $http) ->
  $http.get('/api/globalTimeline').success (posts) ->
    $scope.posts = posts

get compiled to Javascript as follows:

(function() {
  var GlobalTimelineController;

  GlobalTimelineController = function($scope, $http) {
    return $http.get('/api/globalTimeline').success(function(posts) {
      return $scope.posts = posts;
    });
  };

}).call(this);

I wonder about any side effects of these return statements added by Coffee compiler? Both correctness and performance wise?

Should I care about this and and empty returns at the end of my methods and callbacks?

2 Answers 2

1

The $http.get call returns a so-called "promise", which works as follows:

promise.success = function(fn) {
  promise.then(function(response) {
    fn(response.data, response.status, response.headers, config);
  });
  return promise;
};

Taken from AngularJS source code (/src/ng/http.js:700)

This means that whatever Your function returns is ignored, and so if it was object, the reference to it is lost just after Your function is done. Therefore, from correctness point of view it doesn't really matter.

Now if we look at performance, in this case the difference, if any, is negligible. However, You always need to keep that behaviour in mind. If the last thing You did in Your function was executing some loop with many iterations, coffeescript would return a big array consisting of results of each array iteration (array comprehension). Not only can it affect performance, but in extreme cases might result in JS memory shortage!

You can also append a return statement at the end to prevent coffeescript from producing such arrays.

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

Comments

1

TLDR; If don't think you should worry about that.

The only problem dealt with looong time ago was related to unit testing controller methods.

Let's say, in your unit tests you have something like this:

  beforeEach inject ($injector)->
    $controller       = $injector.get '$controller'
    injectables   = { ... }
    ctrl = $controller 'app.controllers.FooBarCtrl', injectables


  describe 'Controller ...', ->
    it 'should have foo property', ->
      expect(ctrl.foo).toBeDefined()

And your controller looks like this:

name = 'app.controllers.FooBarCtrl'
angular.module(name, []).controller(name, [

  '$scope'
  '$http'

  ($scope)->
    scope.foo = 'bar'
    $http.get '/foo/bar', (res)-> console.log 'response: ', res

])

In this case, you wouldn't be able to test any controller methods, since what is returned is actually a promise. in order to gain access to actual controller methods you would need to return this, like here:

name = 'app.controllers.FooBarCtrl'
angular.module(name, []).controller(name, [

  '$scope'
  '$http'

  ($scope)->
    scope.foo = 'bar'
    $http.get '/foo/bar', (res)-> console.log 'response: ', res

    @ # <--- look ma, I'm here!
])

However, I think these examples are not very relevant from practical point of view, since in unit testing angular controllers you should actually deal with the API provided with $scope and consider controller methods as private (implementation details).

2 Comments

Thanks Rafal, that's helpful input on unit tests. But I'm going with catvir's answer, since it gives more detail about return values and possible performance gotchas.
Cheers, np, I didn't want to repeat other answers here.

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.