1

Consider you have a simple, standard $http request to a REST api:

...
function makeCall() {
    var restURL = "http://my-rest-api/endpoint";
    return $http.get(restURL);
}
...

If the execution time of this call varies for whatever reason (sometimes returns immediately, other times takes around a second to e), what is the best practice for normalizing the response time to the user?

In the past, I've done things like this:

...
function makeCall() {
    var restURL = "http://my-rest-api/endpoint";
    return $http.get(restURL);
}

...

function myController($scope) {
    var promise = makeCall(); //make rest call
    $scope.waitMessage = true;
    $timeout(function() {
        //before resolving the promise, wait a certain number of ms, then
        //resolve and display data to user
        promise.then(function(response) {
            $scope.output = response.data;
            $scope.waitMessage = false;
        });
    }, 1000);
}

This is an attempt to make the request take a fixed amount of time, regardless of if it returned immediately or not. During the delay time, I display an interstitial of some kind saying "Loading, please wait..." or the like, controlled by a variable like $scope.waitMessage.

Any best practices for this sort of use case?

4
  • 2
    Why would you ever want to increase latency? Decreasing spikes by speeding up the things that take long, sure, but deliberately wasting time and resources to make things take longer for those you could serve more quickly? That's not even fair scheduling, if anything waiting some more makes the slow calls even (marginally) slower.
    – user7043
    Mar 15, 2015 at 16:47
  • I agree increasing latency is far from ideal. I am trying to deal with the UX issue of having the "loading" interstitial show and hide so fast it appears to flicker. (for immediate calls) The goal of the original approach is to fine tune a delay time so it's the max wait time all calls take (slow and fast). For example if the "fast" use case is 100ms and the "slow" use case is 800ms, make all calls take 900ms. Not defending the approach, just clarifying. Mar 15, 2015 at 17:08
  • 1
    You have an XY problem. You should be asking how to make the loading screen look better (not flicker).
    – user7043
    Mar 15, 2015 at 17:28
  • Fair enough. I am still interested to hear thoughts on solutions for this use case however. Thanks for your input as simply discussing this has helped me think of a few solutions I can try. Mar 15, 2015 at 18:13

1 Answer 1

1

I'm not sure if it's a "best practice", but my way is to create a directive that throttles variable changes, using the lodash/underscore throttle function:

app.directive('throttle', function($window) {
  var WAIT_TIME = 750;

  return {
    scope: true,
    link: function(scope, element, attrs) {
      var name = attrs.throttle;

      function setValue(value) {
        // Shadow the value in the child scope
        scope[name] = value;

        // The leading edge of the _.throttle callback
        // is called within a digest, but later ones are not
        scope.$$phase || scope.$apply();
      }

      scope.$parent.$watch(name, $window._.throttle(setValue, WAIT_TIME));
    }
  };
});

That can be used for a simple text state variable to determine what to show to the user:

<div throttle="state">
  <div ng-if="state == 'loading'">Loading...</div>
  <div ng-if="state == 'loaded'">[Loaded template]</div>
</div>

So referring to the code in your question, in the controller you could have something like:

$scope.state = 'loading';
makeCall().then(function(response) {
  $scope.output = response.data;
  $scope.state = 'loaded';
});

The benefits of doing this rather than via $timeouts in your controller or services:

  • Better separation of responsibilities. The controller/services don't need to know about exactly how/when the data will be shown to the user. This is just in the template/directive.

  • Throttling means you've set a minimum time any given state will be shown to the user. If the user has been in that state already for at least that time, then there will be no extra time waiting.


I originally posted this on my blog at http://charemza.name/blog/posts/angularjs/templates/angularjs-throttled-variable-changes/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.