I want to call a method on an interval of time. I am receiving stack overflow error. What am I doing wrong:
html:
<div ng-app="myApp" ng-controller="Ctrl">
<span>{{calledServer}}</span>
</div>
js:
var app = angular.module('myApp', []);
app.controller("Ctrl", function($scope, repo, poollingFactory) {
$scope.calledServer;
$scope.calledServer = poollingFactory.callFnOnInterval(function() {return repo.callServer(5);});
});
app.factory("repo", function() {
function callServer(id){
return "call server with id " + id;
}
return {
callServer: callServer
};
});
app.factory("poollingFactory", function($timeout) {
var timeIntervalInSec = 5;
function callFnOnInterval(fn, timeInterval) {
$timeout(callFnOnInterval, 1000 * timeIntervalInSec);
callFnOnInterval(fn, timeIntervalInSec);
};
return {
callFnOnInterval: callFnOnInterval
};
});
jsfiddle: http://jsfiddle.net/fq4vg/423/
You have a recursive call that isn't checking for any precondition.
An annotated version of your function:
function callFnOnInterval(fn, timeInterval) {
//Schedule a call to 'callFnOnInterval' to happen in one second
// and return immediately
$timeout(callFnOnInterval, 1000 * timeIntervalInSec);
//Immediately make a call to 'callFnOnInterval' which will repeat
// this process ad-infinitum
callFnOnInterval(fn, timeIntervalInSec);
};
Because you keep pushing calls onto the stack recursively and never returning, it eventually runs out of space.
Since the $timeout
service returns a promise, you can use that to schedule more work once it is complete.
Here is what your service should probably look like:
app.factory("poollingFactory", function ($timeout) {
var timeIntervalInSec = 5;
function callFnOnInterval(fn, timeInterval) {
var promise = $timeout(fn, 1000 * timeIntervalInSec);
return promise.then(function(){
callFnOnInterval(fn, timeInterval);
});
};
return {
callFnOnInterval: callFnOnInterval
};
});
And here is an example jsFiddle to demonstrate: http://jsfiddle.net/jwcarroll/cXX2S/
A few notes about your code above.
You are trying to set a scope property value to the return of your callFnOnInterval
but that isn't going to work. First, it doesn't return anything. Second, because it is an asynchronous call, at best it could return a promise
.
Your timeout method is calling itself until he runs out of space.
If you want to do something every x seconds use the $interval method.
app.factory("poollingFactory", function($interval) {
var timeIntervalInSec = 5;
function callFnOnInterval(fn, timeInterval) {
return $interval(fn, 1000 * timeIntervalInSec);
};
return {
callFnOnInterval: callFnOnInterval
};
});
by the way, to get the result of the method back into your scope property you have to change the call to:
poollingFactory.callFnOnInterval(function() {return $scope.calledServer = repo.callServer(5);});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With