Adam James February 2016

What is the purpose of a return {...} block in AngularJS services?

I'm starting to learn the basics of AngularJS and looking at some example code:

'use strict';

angular.module('someModule')
.factory('DateFormatter', function () {
  var clean = function (date) {
    return moment(date).format('YYYY-MM-DD');
  };

  return {
    clean:clean
  };
});

Can anyone tell me why it is necessary (or best practice, perhaps?) to include the return block at the bottom? Does it make the clean() function accessible to external code or something like that?

Thanks

Answers


Patrick Kelleter February 2016

you could as well write

angular.module('someModule')
.factory('DateFormatter', function () {
  return {
    clean: function (date) {
      return moment(date).format('YYYY-MM-DD');
    };
  }
});

it's the exact same thing. but for bigger functions with more code the first one is more readable. so yeah, it's simply best practice, but not necessary


Claies February 2016

From the angular documentation on providers:

The Factory recipe constructs a new service using a function with zero or more arguments (these are dependencies on other services). The return value of this function is the service instance created by this recipe.

In your example, the factory is returning an anonymous object, with a .clean property. The order in which you declare these does not matter; You can declare the return first, or the functions first, or declare the functions inline; all will achieve the same effect.

//form 1
var clean = function(date) {
  return moment(date).format('YYYY-MM-DD');
};

return {
  clean: clean
};

//form 2
var service = {
  clean: clean
};

return service;

function clean(date) {
  return moment(date).format('YYYY-MM-DD');
};

//form 3
return {
  clean: function(date) {
    return moment(date).format('YYYY-MM-DD');
  };
};

The recommended form is form 2, in the popular style guide created by John Papa. The reasoning for this is that by declaring the callable members at the top, you can immediately see what the factory will return without needing to scan past the implementation details.


Balázs February 2016

By using the factory method, you pretty much tell AngularJS that whenever an object of DateFormatter is requested (for example, by the dependency injection mechanism), it should execute the method you pass to the second parameter to factory(..., ...), and supply the object returned by that function rather than the function itself.

That is, Angular will not provide the method you define, but the object that method returns. This is pretty much what the word 'factory' refers to: 'create this object for me when I ask for it'.

If it returned the function, all that would change is you would have to call the function by yourself so that it provides you with some value/object, such as this:

.controller(DateFormatter) {
  // If Angular returned the function rather than it's returned value,
  // you would have to do this in order to get access to the clean function:
  (DateFormatter()).clean();
}

In another sense, your assumption that it makes the clean function accessible is right. To this end, it also provides sort of an encapsulation mechanism. If you did this:

angular.module('someModule')
.factory('DateFormatter', function () {
  var clean = function (date) {
    date = someHelperFunction(date);
    return moment(date).format('YYYY-MM-DD');
  };

  var someHelperFunction(date) {
    // do something here with date
  };

  return {
    clean:clean
  };
});

then you are able to call the someHelperFunction function from inside, but not from outside since you do not return it.

Post Status

Asked in February 2016
Viewed 3,139 times
Voted 12
Answered 3 times

Search




Leave an answer