Bin Wang
Bin Wang

Reputation: 2747

How to handle asynchronous in angular.js controller?

I'm new to angular.js. I'm confused with how to handle asynchronous events in the controller.

For example, in a page, I have a view named count. And while I click on a button, the controller increase the count by 1. But the increase is asynchronous. What I want is, when count changed, the view will be notified and change its value. But util the next click, the view will not change its value.

This is the code for example:

<!DOCTYPE html>
<html ng-app>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
  </head>

  <body>
    <div ng-controller="Controller">
      {{ count }}
      <form ng-submit="delayInc()">
        <input type="submit" value="Add" />
      </form>
    </div>

    <script>
      function Controller($scope) {
        $scope.count = 0;

        $scope.delayInc = function () {
          setTimeout(function () {
            $scope.count += 1;
          }, 1000);
        };
      }
    </script>
  </body>
</html>

Update:

Thanks for all your answers. But I'm asking a generate question. How about the setTimeout function is a http request? I know there is $http could do this. But what if the function is something handle a file and so on? I don't except every async call have a service for me. Do I need to write my own one if it dose not exist?

Upvotes: 1

Views: 2137

Answers (2)

lucassp
lucassp

Reputation: 4167

Due to the nature of the AngularJS $scope you need to replace the setTimeout call with the $timeout service.

Upvotes: 0

James Allardice
James Allardice

Reputation: 165941

Use the $timeout service instead of the native setTimeout:

function Controller($scope, $timeout) {
    //                      ^---- Don't forget to inject the service
    $scope.count = 0;

    $scope.delayInc = function () {
        $timeout(function () {
            $scope.count += 1;
        }, 1000);
    };
}

Alternatively, you can tell Angular to apply your changes manually using Scope.$digest() (the $timeout service shown above will effectively do this for you):

function Controller($scope) {
    $scope.count = 0;

    $scope.delayInc = function () {
        setTimeout(function () {
            $scope.count += 1;
            $scope.$digest();
        }, 1000);
    };
}

Upvotes: 4

Related Questions