9

I have a very simple app that loads a JSON array using $http.get inside of a controller. It assigns the result data to scope and the HTML repeats through the results to display a list. It is a very simple angularjs example.

function ViewListCtrl($scope, $http) {

$scope.shoppinglist = [];

$scope.loadList = function () {

    var httpRequest = $http({
        method: 'POST',
        url: 'viewList_service.asp',
        data: ''

    }).success(function (data, status) {
        $scope.shoppinglist = data;
    });

};

$scope.loadList();

}

While testing on a slow server I realized there was a 3 second blocking delay while rending the repeat region. Debugging revealed to me that my controller does not attempt to get the data until the page is loaded. My page takes 3 seconds to load. Then I must wait another 3 seconds for the json data to load.

I want to load data as soon as possible so it is ready when my controller is ready. Simply put, I want to pre-load the data so it loads in parallel to my module.

I've searched all over and the closest thing I found was "resolve", but I am not using routes. This is a very simple list and no routes or templates.

How can I load the JSON as soon as the page starts to render so it is ready when the controller is ready and there is no blocking... and then get that data into scope?

1
  • Are you sure your function is called after onload() event? If so, you can call it before onload() itself, thereby saving those 3 seconds. You might wanna have a look at this question. Commented Dec 20, 2013 at 8:06

3 Answers 3

3

You can use the module.run method. Which is executed after the config stage is completed. To make use of this you need to create a service factory that does the actual query and caches the result

module("myapp",[]).factory('listService', function($q,$http) {
    var listData;
    var defer = $q.defer();
    return  {
       loadList: function() {
          if(listData) {
               defer.resolve(listData);
          }
          else {

              var httpRequest = $http({
                 method: 'POST',
                 url: 'viewList_service.asp',
                 data: ''
             })
             .success(function(data) { 
                 listData=data;
                 defer.resolve(listData);
             }
        }
        return defer.promise;
   }
}
});

In your controller you still use the factory to get the data with a promise then wrapper.

listService.loadList().then(function(data) {
   $scope.shoppinglist=data;

});

This way you can make the async call even before any controller related code executes.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the reply. This works, but I how do I use module.run. I just put "listService.loadList()..." into my controller but it has the same loading delay. So I assume I am suppose to use module.run like the other answer. If listService.loadList goes in my controller then what goes in module.run?
Same call goes both places. First in module.run because it executes first. If the page too is loaded meanwhile the second call may just get the cache data.
Thank you. I got this working and it seems that run does not load much faster than my controller. Both wait for the DOM to be ready and that is taking about 1.5 seconds. This seems to be the source of my issue. I don't want to wait 1.5 seconds to start downloading the data. Is there anyway to start getting the data before the DOM is ready? Is the only way to have the data embedded server side?
1

You can load data by writing code (something like Chandermani's listService) in separate file but without using angular. you can use jquery ajax to load your data.

Then write a service in angular to read that data and pass it to your controller.

2 Comments

I wonder if jQuery will have the same issue in that is cannot load data until after the Dom is ready, which is taking 1. 5 seconds on this site. I don't want to wait 1.5 seconds to start getting data.
JQuery has not this issue. JQuery has $(document).ready function that act after dom get ready. But if you don't use ready function you can write code that executed in page load time.
0

It sounds like your latency comes from a slow network + server, and not a large amount of data.

So, you could render a tag into your page, so that the data would be sent along with the page HTML response. The downside there is that you're hard-coding your data into your page. This tag would basically pre-seed the $http cache with your data.

var listJson = {...json data here, rendered server-side...};

mod.run(function($cacheFactory) {
  var cache = $cacheFactory('yourListCacheId');
  cache.put('list-cache-id', listJson);
  // store "cache" somewhere you can retrieve it, such as a service or value.
});

Then either use the $http cache property, or wrap $http in a custom service which checks the cache.

Of course, the root of the problem is that your server takes 3 seconds per request, when you normally want that at least in the sub-second range.

1 Comment

Thank you. I cannot send the data with the page load. The data is being obtained from a service. Can http method be used from inside mod.run? Yes, the root of the problem is the server takes 3 seconds. However, if I can get data while page loads, then page takes 3 seconds instead of 6.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.