Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Service Definition: service or factory

I am an angular newbie, I am building an application, one thing really puzzling me is there are couple of ways of defining a service, and I read more from this link: How to define service then it seems there is no big difference among the ways of defining a service.

but I just noticed one difference which I think is different:

see this service I get from here http://jsfiddle.net/2by3X/5/

var app = angular.module('myApp', []);
app.service('test', function($timeout, $q) {
  var self = this;
  this.getSomething = function() {
    return self.getData().then(function(data) {
      return self.compactData(data);
    });
  };
  this.getData = function() {
    var deferred = $q.defer();

      $timeout(function() {
          deferred.resolve("foo");
      }, 2000);
    return deferred.promise;
  };
  this.compactData = function(data) {
    var deferred = $q.defer();

    console.log(data);

    $timeout(function() {
        deferred.resolve("bar");
    }, 2000);
    return deferred.promise;
  };
});

if I define this service using "factory" like below, one function cannot call other functions of the service.

app.factory('test', function($timeout, $q) {
  return {
      getSomething : function() {
    return getData().then(function(data) {
      return compactData(data);
    });
  },

      getData : function() {
    var deferred = $q.defer();

      $timeout(function() {
          deferred.resolve("foo");
      }, 2000);
    return deferred.promise;
  },

      compactData : function(data) {
    var deferred = $q.defer();

    console.log(data);

    $timeout(function() {
        deferred.resolve("bar");
    }, 2000);
    return deferred.promise;
  },
 };
});

I will get this in the browser console:

[08:41:13.701] "Error: getData is not defined
.getSomething@http://fiddle.jshell.net/_display/:47
Ctrl1@http://fiddle.jshell.net/_display/:75
invoke@http://code.angularjs.org/1.0.0/angular-1.0.0.js:2795
instantiate@http://code.angularjs.org/1.0.0/angular-1.0.0.js:2805

Can anyone explain this? thanks.

like image 919
John Ding Avatar asked Jul 03 '13 13:07

John Ding


1 Answers

you have two big problems there:

  • the factory returns an object with incorrect syntax.
  • javascript scope of variables is functional

That is, You should be returning an object like {key: value, key: value}

values can be functions. however, you return {key = value, key = value}

First fix:

return { 
    getSomething : function() {...},
    getData : function... 
}

Secondly, not being able to call functions is normal. See this jsfiddle. I mocked everything. You can call one of the functions returned by the service. However, when from getSomething try to call getData, you get "undefined":

app.factory('testSO', function () {
return {
    getSomething: function () {
        console.log('return getsomething');
        getData();
    },

    getData: function () {
        console.log('return getData');
    }...

This would be the same as declaring everything in the scope of the factory function and return references see in jsfiddle:

app.factory('testSO', function () {
    var getSomething = function () {
        console.log('return getsomething');
    };
    ...
return {
    getSomething: getSomething,
    ...
}

and now you can call local functions as shown in the final version of the jsfiddle:

app.factory('testSO', function () {
    var getSomething = function () {
        console.log('return getsomething');
        getData();
    };
...

The original service has something important in it: var self = this; . Some people use var that = this. It's a workaround for an error in ECMA. In the case of the original code, it's used to "put everything in one object". Functions (properties that happen to be functions) in self need a reference to know where the function you want to call is. Try it yourself here http://jsfiddle.net/Z2MVt/7/

like image 132
Eduard Gamonal Avatar answered Oct 19 '22 04:10

Eduard Gamonal