Calling a function in AngularJS service from the same service?
AngularjsAngularjs Problem Overview
I have an AngularJS service defined in the following way
angular.module('myService').service('myService', function() {
this.publicFunction(param) {
...
};
this.anotherPublicFunction(param) {
// how to call publicFunction(param)?
...
};
});
and I would like to call the first function both from outside the service (which works fine by myService.publicFunction(xxx)
) and from another function in the same service, i.e. anotherPublicFunction
. Neither one of this.publicFunction(param)
or myService.publicFunction(param)
won't work from within the second function, and I can understand that.
EDIT:
Actually the whole problem was caused by something you can't reproduce with my example alone. I passed the second function as a callback parameter to another function in a separate controller, and when it is called, the reference to this
doesn't work.
E.g.
anotherService.someCall('a', 123, myService.anotherPublicFunction);
fails inside anotherPublicFunction
because this
can't be resolved.
I've written a Plunker to show the problem: http://plnkr.co/edit/rrRs9xnZTNInDVdapiqF?p=info
(I'll still leave the question here in case it will help someone else.)
I know I could get around the problem by using a reference to the service or the first function like this
var ms = this;
this.anotherPublicFunction(param) {
ms.publicFunction(param);
...
};
or this
var pf = this.publicFunction;
this.anotherPublicFunction(param) {
pf(param);
...
};
but both seem like dirty hacks.
Is there a good way to call the first function from the second one in this case? Or am I doing something totally wrong in the first place to have a service like this?
I found these questions with good answers:
- https://stackoverflow.com/questions/16753825/angularjs-share-functions-inside-service
- https://stackoverflow.com/questions/18853797/angularjs-call-an-internal-service-function-from-self
but they differ from my problem since one of them has a separate, internal function that was to be called, and the other one was using a factory instead of a service.
EDIT:
After posting this I immediately realized I could also do this:
var actualWork = function(param) {
...
}
this.publicFunction(param) {
actualWork(param);
};
this.anotherPublicFunction(param) {
actualWork(param);
...
};
which doesn't seem quite as bad as the other options so far... Are there better approaches?
Angularjs Solutions
Solution 1 - Angularjs
I think the best way is to go like this:
var myFunctions =
{
myFunc1: function(param) {
},
myFunc2: function(param) {
return foo + myFunctions.myFunc1(param)// do some stuff with the first function
}
}
return myFunctions;
because I think if you use this, it may get conflict with the scope where you use the service.
Solution 2 - Angularjs
I ran into this problem within my own angular coding and opted to use this form of the solution:
angular.module('myService').service('myService', function() {
var myService = this;
myService.publicFunction(param) {
...
};
myService.anotherPublicFunction(param) {
myService.publicFunction(param);
...
};
});
I preferred this approach because in my code I use publicFunction and inside of anotherPublicFunction I loop over several params that need to call publicFunction as part of the process.
Solution 3 - Angularjs
Sounds good but what do you do when this
is no longer =
the service ?
This is the case in the following example:
return {
myFunc1: function(param) {
},
myFunc2: function(param) {
scope.$watchCollection(param,function(v) {
return foo + this.myFunc1(param)// do some stuff with the first function
}
}
}
Because of function(v) {
you are now in another function within the function and this is no longer the service but the window.
Solution 4 - Angularjs
You can just return an object from within your service like
return {
myFunc1: function(param) {
},
myFunc2: function(param) {
return foo + this.myFunc1(param)// do some stuff with the first function
}
}
So you access it from the outside with service.myFunc1
and from inside its internal functions with this.
Solution 5 - Angularjs
You can set 'this' as variable
angular.module('myService').service('myService', function() {
var that = this;
this.publicFunction(param) {
...
};
this.anotherPublicFunction(param) {
that.publicFunction(param);
};
});
Solution 6 - Angularjs
Well, just create two more pointers/function variables for your service functions with local variables in service and use those to call the service functions from within same service :
angular.module('myService').service('myService', function() {
**var ref1, ref2;**
this.publicFunction = **ref1** = function(param) {
...
};
this.anotherPublicFunction = **ref2** = function(param) {
// how to call publicFunction(param)?
**ref1(argument);**
...
};
});
*
Solution 7 - Angularjs
this is how I implemented:
.service('testSvc', function () {
return {
f1: function (v1) {
alert('f1 > v1=' + v1);
},
f2: function (v2) {
alert('f2 > v2=' + v2);
this.f1('az'); //use 'this'
}
}
})
Solution 8 - Angularjs
Below solution worked for me:-
angular.module('myService').service('myService', function() {
var self= {
this.publicFunction(param) {
...
};
this.anotherPublicFunction(param) {
// You can call the publicfunction like below
self.publicFunction(param);
...
};
return self;
}
]);`
Solution 9 - Angularjs
angular.module('myService').service('myService', function() {
return {
myFunc2: function(param) {
return foo + myFunc1(param);
}
};
function myFunc1(param){
...
};
});
Solution 10 - Angularjs
Best and easiest way to call is:
myapp.service("SomeService", function ($http) {
this.func1 = function (params) {
// Some thing the service returns
return something;
}
this.func2 = function (params) {
// Some thing the service returns
var resp = this.func1(params);
return something;
}
}
Solution 11 - Angularjs
If you want to use the factory declaration instead of service, you can:-
angular.module('myService').factory('myService', function() {
var myService = {};
myService.publicFunction = function(param) {
...
};
myService.anotherPublicFunction = function(param) {
// call publicFunction(param) like so
myService.publicFunction(param);
};
return myService;
});