Call a function periodically on server in background in angularjs - angularjs

I have an API on q server that looks like this:
function isLoggedIn(){
....
}
This API tell whether a user is logged in or not.
I want to call this API every 15 minutes or within any interval, to check whether the user is authenticated or not on my angular app.
My concern is how to call an API in intervals, and where to write this method.

Use setInterval in your main controller.
setInterval(function(){
// call your service method here
//isLoggedIn(); in your case
}, 3000); // This is time period in milliseconds 1000 ms = 1 second.
Or
use $interval service is injected into your controller function, you can use it to schedule repeated function calls. Here is an example that used the $interval service to schedule a function call every 5 seconds:
var myapp = angular.module("myapp", []);
myapp.controller("MyController", function($scope, $interval){
$interval(isLoggedIn, 5000);
});
function isLoggedIn() {
console.log("Interval occurred");
// call your service method here
}

Here is my code that I use.
app.run(
function ( $interval, AuthService, $state, $rootScope, $http, $location, $stateParams ) {
$interval( function( event, toState, toParams, fromState, fromParams ){
AuthService.keepAlive( $rootScope, $http ).then( function( data ){
if( data.Result == "false" ){
AuthService.logout( $http, $rootScope ).then( function( data ){
$rootScope.returnToState = $location.url();
//$rootScope.returnToStateParams = toParams.Id;
$state.transitionTo("login.signin");
//event.preventDefault();
});
}
});
}, 1000 * 60 );
});
its working. I can ping server minute. I am getting response properly.
Small problem when I will remove comment from event.preventDefault I am getting event is not defined.
if possible can you please tell me.

Related

How to call function every 10 seconds?

How to call function every 10 seconds? $timeout and setTimeout calling the function dataTime only one time, I would like repeating this constantly with no end.
angular
.module('sfcLeftSiteBar')
.component('leftSiteBar', {
templateUrl: '/Panel/LeftSiteBar/Templates/_leftSiteBar.html',
controller: ['$http', '$window', '$state', '$scope', '$timeout', function ($http, $window, $state, $scope, $timeout) {
function dataTime() {
$http.post('/LeftSiteBar/TimeProvider').then(function (result) {
console.log("czas" + JSON.stringify(result))
$scope.datatime = result.data;
console.log("czas2" + JSON.stringify($scope.datatime))
})
}
// $timeout(dataTime, 10000);
setTimeout(dataTime, 10000);
}]
})
Angularjs has a built-in $interval, you should use it instead of regular setInterval:
controller: ['$interval', '$scope', function($interval, $scope) {
function dataTime() {
console.log('function works');
}
// start interval
var interval = $interval(dataTime, 10000);
// call this method to stop interval
$scope.stop = function() {
$interval.cancel(interval);
};
}
More info about $interval
You can use setInterval instead of setTimeout, like so:
setInterval(dataTime, 10000);
In order to be able to clear the interval at a later date, you need to assign a variable the return value of setInterval and then call clearInterval with your interval as parameter, like so:
var myInterval = setInterval(dataTime, 10000);
//clear interval at some point
clearInterval(myInterval);
But since you are using AngularJS, you might use the built-in interval method that takes care of any changes that might happen in the called function and automatically trigger a digest cycle.
var angularInterval = $interval(dataTime, 10000);
And cancel it like so:
$interval.cancel(angularInterval);
Use angularjs $interval service to handle that. It is a angular service and comes with all you need in your application
stop = $interval(function() {
dataTime();
}, 100);
You can also cancel the continous execution if you want.
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
}
<html>
<body>
<p>Click the button to wait 3 seconds, then alert "Hello".</p>
<p>After clicking away the alert box, an new alert box will appear in 3 seconds. This goes on forever...</p>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction() {
setInterval(function(){ alert("Hello"); }, 3000);
}
</script>
</body>
</html>
it will execute for every 20 secs
setInterval(function(){
$scope.callingFunction();// we can write any function
}, 20000)

AngularJS factory return no data first time, but after called interval method it does

Im trying to make a AngularJS factory that provides my app with a list of businesses. But i cant seem to get the variable the first time this is run. But after interval is run, i get the variable.
I get this on the first run on the controller in the page:
angular.js:12783 Error: [$injector:undef] Provider 'businessList' must return a value from $get factory method
But I think my solution is faulty, any how? Can anyone point me in the right direction here? For example is using rootScope here a good idea?
What I want is a globally accessible list of businesses in my app, that is collected on start of visit, and updates itself with a timer. So i dont have to all the time call for induvidial requests from the laravel backend, when i can just find it in that list.. is my idea.
Factory:
myApp.factory('businessList', ['$interval', '$http', '$rootScope',
function($interval, $http, $rootScope) {
function bedriftliste() {
$http.get('get/allebedrifter')
.then(function(result) {
bedrifter = result.data;
$rootScope.bedrifter = bedrifter;
});
return $rootScope.bedrifter;
}
var bedrifter = bedriftliste();
// start periodic checking
$interval(bedriftliste, 5000);
return bedrifter;
}
]);
Controller
myApp.controller('bsC', ['$rootScope', '$scope', 'businessList',
function($rootScope, $scope, businessList) {
$scope.allebedrifter = businessList;
}]);`
I solved this by just doing a http.get if object was null.
if (!$rootScope.allebedrifter) {
$http.get('get/bedrift/' + $scope.tslug)
.then(function(result) {
bedriften = result.data;
$scope.bedriften = bedriften;
});
Seems to work fine like this
Although I am late in pointing out but that doesn't seem to be a proper solution to this problem. You need to make these changes in factory:
myApp.factory('businessList', ['$interval', '$http', '$rootScope',
function($interval, $http, $rootScope) {
function bedriftliste() {
return $http.get('get/allebedrifter');
}
}
]);
and in the controller you'll do something like this:
myApp.controller('bsC', ['$rootScope', '$scope', 'businessList', function($rootScope, $scope, businessList) {
function TestFunction(){
businessList.bedriftliste().then(function successCallback(response) {
$scope.allebedrifter = response.data;
//it will invoke 5 seconds after you receive the response from your factory method, I didn't test it but it will solve your problem
$interval(TestFunction, 5000);
}, function errorCallback(response) {
});
}
}]);

Angular JS: using $interval to refresh service data

I am facing following problem:
In my AngularJS application, I have service, which includes data and a function, which refreshes them
angular.module('testService', ['ui.router'])
.factory('testService', function($http) {
var service = {};
var _baseUrl = 'http://127.0.0.1:8000/api/v1/test/';
service.orders = {created: 0, approved: 0};
/*
* get number of unprocessed orders
*/
service.updateNOrders = function(){
var tableName = 'orders?stats=true';
$http({
method: 'GET',
url: _baseUrl + tableName,
}).success(function(data){
service.orders = data;
console.log(data);
return;
}).error(function(err){
alert(JSON.stringify(err));
return;
})
}
});
I can inject this service to i.e. directive and call the function updateNOrders to update the data from the directive.
What I want, though, is for service to call this function every n seconds.
The service is shared in several directives and instead of every directive, taking care of updating the data, I would like the service to do it itself.
I have tried comething like:
angular.module('testService', ['ui.router'])
.factory('testService', function($http, $q, $rootScope, $interval) {
$interval(console.log('test'),1000);
/*
rest of the code
*/
});
but that does not work.
So - Is it possible to call the function updateNOrders inside testService every minute or so?
Creating service with side effect is the bad idea. Better off create service with method which sets your interval with callback. Then you can inject your service in run callback (run calls callback only once):
angular.module('testService', ['ui.router'])
.factory('testService', ['$interval', function($interval) {
var service = {};
service.doPeriodicAjaxRequest = doPeriodicAjaxRequest;
function doPeriodicAjaxRequest() {
$interval(yourCode, ...);
}
return service;
}]);
Then:
angular.module('', [])
.run(['testService', function (testService) {
testService.doPeriodicAjaxRequest();
}]);
Why dont you call the service function from controller in certain interval of time.
$interval(testService.functionName,1000);

Alternatives to angularjs $watch to trigger ui change from service

I'm wondering whether there is a different approach to using $watch in order to achieve the following.
Setup:
ControllerA depends on ServiceA.
ControllerB depends on ServiceB.
Current browser view is showing both controllers.
Scenario:
ControllerA is initiating a function on ServiceA, which in turn changes the value of propery X in ServiceB which should be reflected in the UI of ControllerB.
http://jsfiddle.net/zexscvax/2/
html:
<div>
<div ng-controller="ControllerA"></div>
<div ng-controller="ControllerB">Progress: {{progress}}</div>
</div>
js:
var myApp = angular.module('myApp', []);
myApp.factory('serviceA', ['$q', '$interval', 'serviceB', function ($q, $interval, serviceB) {
var service = {};
service.start = function () {
var progress = 0;
var deferred = $q.defer();
deferred.promise.then(null,null, notifyServiceB);
function notifyServiceB() {
serviceB.update(progress);
}
$interval(function() {
if (progress == 0.99) {
deferred.resolve();
} else {
progress += 0.01;
deferred.notify(progress);
}
}, 50, 100);
};
return service;
}]);
myApp.factory('serviceB', ['$rootScope', function ($rootScope) {
var service = {};
service.update = function (progress) {
console.log('update', progress);
service.progress = progress;
//$rootScope.$apply(); // <+ ERROR: $digest already in progress
};
return service;
}]);
myApp.controller('ControllerA', ['$scope', 'serviceA',
function ($scope, serviceA) {
serviceA.start();
}]);
myApp.controller('ControllerB', ['$scope', 'serviceB',
function ($scope, serviceB) {
$scope.progress = serviceB.progress;
/* this works but I'm not sure whether this is performing
$scope.$watch(function () { return serviceB.progress; },
function (value) {
$scope.progress = serviceB.progress;
}
);
*/
}]);
Without the $watch in ControllerB for the property X in ServiceB, the UI would not get updated. I've also tried injecting $rootScope in ServiceB in order to run an apply() but that wouldn't work.
I'm not entirely sure whether there's a better way to setup this scenario or whether $watch is fine. I'm a bit worried about performance issues as the value of property X changes almost every 50 ms (it's basically a visual timer counting down).
Thanks for your input.
If you don't use $watch, you can use $rootScope to broadcast, and on controller B, you can $on this event and handle the view update.

AngularJS run service function before other functions

I am new to AngularJS and have a service that loads my initial user configuration
angular.module('myApp').service('myService', ['$http', function ($http) {
var self = this;
self.user = {};
self.loadConfiguration = function () {
$http.get('/UserConfig').then(function (result) {
self.user = result.data;
});
};
self.loadConfiguration();
}]);
I have a controller that uses the configuration from this service
angular.module('myApp').controller('myController', ['$scope', 'myService', function ($scope, myService) {
var self = this;
// calculation based on service value
self.something = myService.user.something * something else;
}]);
The problem here is that myService.user.something may be undefined since the AJAX request may not have completed when this code is called. Is there a way to have the service complete before any other code is run? I want the service function 'loadConfiguration' to be run only once irrespective of the number of controllers that depend on it.
You can call your service method inside .run() function
Run Blocks
Run blocks are the closest thing in Angular to the main
method. A run block is the code which needs to run to kickstart the
application. It is executed after all of the service have been
configured and the injector has been created. Run blocks typically
contain code which is hard to unit-test, and for this reason should be
declared in isolated modules, so that they can be ignored in the
unit-tests.
https://docs.angularjs.org/guide/module
angular.module('myApp').run(function()){
//use your service here
}
One way to deal with ajax delay, is use $rootScope.$broadcast() function on $http.success which will broadcast your custom event to all controllers. Antoher way is to use promises and perform actions in controllers after resolve. Here are some ideas: https://groups.google.com/forum/#!topic/angular/qagzXXhS_VI/discussion
If you want to make sure that your code in controller gets executed after your AJAX call returns, you may use events.
Use this in your service:
angular.module('myApp').service('myService', ['$http', '$rootScope', function ($http, $rootScope) {
var self = this;
self.user = {};
self.loadConfiguration = function () {
$http.get('/UserConfig').then(function (result) {
self.user = result.data;
$rootScope.$broadcast('myService:getUserConfigSuccess');
});
};
self.loadConfiguration();
}]);
In your controller:
angular.module('myApp').controller('myController', ['$scope', 'myService', function ($scope, myService) {
var self = this;
$scope.$on('myService:getUserConfigSuccess', function() {
// calculation based on service value
self.something = myService.user.something * something else;
})
}]);
You can even attach an object to the event.
Please refer to https://docs.angularjs.org/api/ng/type/$rootScope.Scope .

Resources