Freewind
Freewind

Reputation: 198248

How to let angularjs show fast part first, then render slow part?

I have a big angularjs html page, the rendering of angularjs will take a lot of time. So the page is almost blank at first, and after a while, it shows everything suddenly.

I wonder if there is any way to make the fast part shows first, and the slow part will show later, so the user won't be surprised by a blank page.

I made a simple demo:

<!DOCTYPE html>

<html ng-app>
<head>
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script>
</head>
<body ng-controller="Ctrl">
<button ng-click="go()">Go</button>
<hr/>
<div>Fast</div>
<button ng-repeat="name in fastNames">{{name}}</button>
<hr/>
<div>Slow</div>
<button ng-repeat="name in slowNames">{{name}}</button>
</body>
</html>
<script type="text/javascript">
    function Ctrl($scope) {
        $scope.fastNames = [];
        $scope.slowNames = [];

        $scope.go = function () {
          $scope.fast();
          $scope.slow();
        }

        $scope.fast = function() {
          $scope.fastNames = ["F1", "F2"];
        };

        $scope.slow = function() {
          for (var i = 0; i < 50000000; i++) {
            new Date();
          }
          $scope.slowNames = ["S1", "S2"];          
        }


    }
</script>

You can see there are two parts -- "fast names" and "slow names". I hope the fast names can show as soon as possible, then the slow names. But for now, they won't show at first, and after a while, they show together.

I created a live demo: http://plnkr.co/edit/9lW2TbLBkCB1hhgBVGmo?p=preview

What should I do?

Upvotes: 0

Views: 2108

Answers (1)

Mark Rajcok
Mark Rajcok

Reputation: 364697

As mentioned in the comments, the browser won't get a chance to render until go() returns (JavaScript is single-threaded). Split up the go() function and put the slow part into a separate function that is called asynchronously, via $timeout. To ensure the browser has a chance to render before calling the $timeout callback, give the $timeout a delay of say 50ms.

$scope.go = function () {
   $scope.fast();
   $timeout(function() {
      $scope.slow();
   },50);  // give browser time to render
};

Plunker

Upvotes: 2

Related Questions