3

How can I start fetching data from the server as quickly as possible with Angular?

Currently, most of my page is populated asynchronously via a directive "fooload" placed at the root element:

<html lang="en" ng-app="myapp" fooload ng-controller="MyAppCtrl">
    <head>
        /* bunch of CSS, and other resources */
    </head>

Which loads data into the scope via an http GET request:

angular.module('myapp.directives').
   directive('fooload', function ($http) {
     return {
         link: function (scope, elm, attrs) {
             $http.get('/foo').success(function (data) {
             scope.foo = data;
     });
     }
     };
});

Looking at the network panel, this call is being made in the browser AFTER the requests for the resources referenced in head. How can I make the call to load /foo data as quickly as possible on page load (if possible, even before loading angular itself)?

Filburt
  • 17,626
  • 12
  • 64
  • 115
Chris Han
  • 420
  • 5
  • 13
  • Why would you want to do something like this? Could you describe your usecase? – ganaraj Apr 16 '13 at 22:16
  • I want to pull data from the server to populate the page. It takes a while to load (e.g. 1 sec.). Thus, I want to send the request as soon as possible. This is data that will continue to be polled so long while the user has the page open. – Chris Han Apr 16 '13 at 23:22

3 Answers3

1

This is not really related to Angular, obviously Angular cannot start loading files before Angular has loaded itself. But if the resource (eg /foo) is cacheable by the browser you could add it to a manifest file: http://www.html5rocks.com/en/tutorials/appcache/beginner/

1

I solved this by:

a) fetching the data even before angular loads and storing it in a global variable (I hate using a global variable, but I couldn't think of another way.)

b) manually bootstrapping angular upon load of this data (my app doesn't work at all without the data)

        var $data;
        var ajax_transport = new XMLHttpRequest();

        // Callback for AJAX call
        function responseProcess() {
            if (ajax_transport.readyState !== 4) {
                return;
            }
            if (ajax_transport.responseText) {
                $data = JSON.parse(ajax_transport.responseText);
                    angular.bootstrap(document, ['myApp']);
                });
            }
        }
        // Sending request
        ajax_transport.open("GET", "/mydata", true);
        ajax_transport.onreadystatechange = responseProcess;
        ajax_transport.send();

Note: it's important to remove the tag ng-app="myapp" in your template to avoid automatic bootstrapping.

c) Using the data in my angular app:

        scope.setupSomething($data);

d) Also, to ensure that this data call begins before any other resource load, I started using a resource loader. I liked HeadJs (http://headjs.com/) the most, but the angular folks seem to like script.js (https://github.com/angular/angular-phonecat/blob/master/app/index-async.html)

Criticism or improvements welcome.

Chris Han
  • 420
  • 5
  • 13
0

Start by creating a new service that gets the resource and then bootstraps the document for angular upon success callback from the server.

angular.element(document).ready(function() {
   calllService(function () {
      angular.bootstrap(document);
   });
});

https://stackoverflow.com/a/12657669/1885896

Community
  • 1
  • 1
Brian Petro
  • 1,577
  • 16
  • 32
  • Thanks for the response Brian. I'm not quite sure how this would be significantly faster than a directive? element.ready() is a wrapper of JQuery .ready() which waits until the full DOM is loaded. So I think the call out to pull my data would still only happen after every other resource (CSS, JS, etc.) is fully loaded. – Chris Han Apr 17 '13 at 00:08
  • To my knowledge you are correct. Is a 'loading' display out of the question? – Brian Petro Apr 17 '13 at 00:55
  • It's not out of the question. Though, my current setup results in a 500ms delay which I want to avoid. – Chris Han Apr 17 '13 at 02:57