Find duration of a REST call in Angular.js - angularjs

I want to find out the time taken by a REST service to send back the promise object. If a REST service takes more than lets say x seconds, I need to show user a spinner and once the promise object is obtained the normal flow should proceed.
Any ideas?
Thanks

Recording the time of the request seems unnecessary.
Why not just always setup a timeout that will trigger the spinner after x seconds.
In the success callback of the promise you can just destroy the timeout object preventing it from triggering the spinner if it's before x seconds. Then remove the spinner if it exists.
var duration = 1000 * 1; //1 sec
var timeout = setTimeout(releaseTheSpinner, duration);
var releaseTheSpinner = function() {
//Make spinner
}
Something.update(data).
success(function {
clearTimeout(timeout);
//kill spinner
})

Using setTimeout should suffice. For example:
$scope.useHttp = function() {
$http.get('path/to/stuff')
.success(function(data) {
hideSpinner();
//do stuff with data
});
setTimeout(showSpinner,1000); //will show the spinner after a second (1000 milliseconds).
};

Have a look at the ngProgress directive or the angular loading bar directive, which place a progress at the top of the page. This creates a general, uniform method of displaying progress. Even if the service responds quickly (which is when you don't want to show a progress), the bar moves very quickly. This isn't a direct answer to your question, but a suggested alternative to added complexity around timing and showing a spinner.

Related

API Call after user selection

Um Currently working on an old angular js application.
This has a series of checkboxes where the user can select an option/ several options. for every selection, it does a backend api call. but I want to avoid making a backend call for every selection but allow the user to do his selection for a couple of seconds and then do a backend call at once. I tried to achieve it via a $timeout function, even though it wait for a couple of seconds until the user does the selection, but it does call for the backend API for the number of time I select/deselect the options.
plunker : sample plunker
much appreciate if someone could suggest me a solution.
Thanks
How about just keeping track of whether you are waiting to call the backend. If you are waiting, don't call your function again. Untested code example:
var waiting = false
$scope.toggleCheck = function (option, optionArray, channel) {
var index = optionArray.indexOf(option);
optionArray[index].checked = !(optionArray[index].checked);
if (waiting == false) {
waiting = true //set to true so backend will not be called multiple times
$timeout(function () {
waiting = false
//call the backend api
//access the statuses by $scope.statuses
alert('backend call ' + $scope.statuses);
}, 2000);
}
}
I think what you are looking for is a debounce function. Given a delay in ms, calling the debounce function will start a timer and execute after the timer has reached 0. If we call the same function again, before the timer has reached 0, the timer restarts.
This will prevent the backend from being spammed with API calls if the user frequently clicks the checkboxes.
For more information about debounce, please check out this link (where throttle is also explained): https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf

Autosave form fields for every 15 sec in AgularJS without using $watch

I want to save a form field values every 15 sec with out using $watch and also it should stop executing once it has been moved to a different form. In the form I will be having many fields so I think $ watch will be having performance issue and also am not sure how to call all fields at once for %watch. So I decided to use $interval but I want to stop this execution once I moved to different controller or different form. If user comes back again to this form again this interval function should start automatically. please would you suggest me best way to handle this.
Use $interval like you are planning to do but assign it to a variable
with $scope.on('$destroy', function() { }); callback you can destroy the interval when switching to a different controller.
var intervalPromise = $interval(function() { // your code }, 15000);
$scope.$on('$destroy',function(){
if(intervalPromise)
$interval.cancel(intervalPromise);
});

Stuck with infinitely repeating digest loops

I have an Angular SPA I'm running with Angular Loading Bar and AngularJS v1.4.9.
For some time now, it has been so happening that after the app gets loaded, the bar has been getting stuck after a while, indicating that not all requests are done with. Additionally, one of the console.log()s I have in our code have been firing continuously, around 1-2 times every second. The bar completes and the console.log works normally when the user reloads the page(but doesn't stop on its own).
The console.log() is set inside a function attached to a ng-disabled directive, so I know it's an indicator of a digest cycle in progress.
I use Chrome as my browser and I recently did a profiling run.
Here's some screenshots of what I see:
This is a broad view. As is shown here, it's first happening at 100ms, then at 400, then at 600, and so on(I did a 3s run).
This is the very first vertical strip. Not all of them look exactly the same as this one, but the completeOutstandingRequest, timeout and Browser.self.defer methods are always there. The searchDisable and log methods are ours, the log is the one I'm talking about above.
Here's another one for comparison, but this is slightly different - it has another Browser method: self.url. I'm not sure what it does.
Here are some issues I found which could be related:
Timeout callback can occur in the middle of a digest cycle in Firefox
$browser.defer ends up triggering changeDetection in zonejs through settimeout
P.S. I think this issue first started when we added some interceptors to our code to do some automatic redirects - e.g. when the session has timed out and the user clicks on something, he's automatically returned to the login page to relogin.
This is the interceptor:
interceptor.$inject = ['$rootScope', '$q'];
function interceptor($rootScope, $q) {
return {
responseError: function (rejection) {
var config = rejection.config || {};
if (!config.ignoreAuthModule) {
switch (rejection.status) {
case 401:
var deferred = $q.defer();
$rootScope.$broadcast('event:auth-loginRequired', rejection);
return deferred.promise;
case 403:
$rootScope.$broadcast('event:auth-forbidden', rejection);
break;
}
}
return $q.reject(rejection);
}
};
}
$httpProvider.interceptors.push(interceptor);
This issue has been solved.
It turns out that in case of any Unauthorized requests, the promise that is returned on line 11 above was remaining pending forever, because there was no call to .resolve() or .reject() in the deferred object.
As a result, the loading bar's interceptor was blocked.
I ended up removing the custom promise entirely and that solved the problem.

Scroll AngularJS ngRepeat with Ajax loading data

First of all a plunk: http://embed.plnkr.co/C866y3LHCE7QfBGuFQPQ/preview
So here I'm getting a set of posts via Ajax and displaying them using ngRepeat. Then (when the posts are done rendering) I want to scroll the page to a specific post (let's say post №18). Seems simple, but I can't get it working.
The problem seems to be that angular can't find that post after it receives the data from Ajax, so the position() and scrollTop() functions are not working.
You have to wait until after the view has been updated with your new model, use $timeout waiting 0 milliseconds to scroll immediately after the DOM is ready
plunkr
$scope.getPosts = function() {
$http.get(data_url).success(function(data){
$scope.posts = data;
$timeout(function() {
var post = $('#pid_18');
console.log('pid_18', post);
$('body').scrollTop(post[0].offsetTop);
}, 0);
});
I think the problem is that the render is not finish then if you have 2 element it's could be work but not with 1000.
So the best way is to know when the rendering is finish, a related post :
Calling a function when ng-repeat has finished

Showing AngularJS $timeout progress bar

I have a alert message that I want to hide after a while. I use $timeout and it works well. However, I want to add a small horizontal count-down (aka progress) bar at the bottom of this alert box to let the user know that their time is running out.
AngularJS $timeout doesn't seem to have any way to determine how long it has been running. How should I update my progressbar in this case?
I use the $timeout like this
$timeout(function(){
$scope.m.hideAlertMessage = true;
}, 10000)
You should use $interval to run on every second and update the counter scope variable, and when it gets to 10 you can kill the interval and do whatever you wanted to do.
E.g.
$scope.counter = 0;
$interval(function() {
$scope.counter++;
if($scope.counter == 10) {
// Do whatever you wanted
}
}, 1000, 10);
The third argument of $interval is the # of times to run.
Note that by default this is run in an iteration of $scope.$apply() so the changes to $scope.counter will be immediately visible in your view.

Resources