AngularJS
JavaScript

Search for '{{search_term}}'

Автоматический счетчик на AngularJS

CMOS is the Code-Maven Open Source podcast that also includes video interviews. Subscribe to this feed RSS feed with your Podcast listener app or via iTunes iTunes.

Мы видели как создать счетчик на AngularJS, который мы увеличивали или уменьшали с помощью нажатий на кнопку. В этом примере мы будем автоматически увеличивать счетчик с течением времени.

Не забудьте ознакомиться с другими примерами счетчиков!

Планирование будущего выполнения, используя $timeout

examples/angular/automatic_counter.html

<script src="angular.min.js"></script>
<script>
angular.module('CounterApp', [])
    .controller('CounterController', function($scope, $timeout) {
        $scope.counter = 0;
        var updateCounter = function() {
            $scope.counter++;
            $timeout(updateCounter, 1000);
        };
        updateCounter();
    });
</script>
<div ng-app="CounterApp">
   <div ng-controller="CounterController">
   {{counter}}
   </div>
</div>
Try!

В этом примере функция контроллера ожидает два параметра. $scope - содержит атрибуты, с которыми мы взаимодействуем в нашем HTML, и $timeout - это функция, похожая на setTimeout из обычного Javascript. (На самом деле это называется внедрение зависимости, а не параметры, но пока не будем беспокоиться об этом. Особенно, пока я сам этого не понимаю.)

$timeout это функция, которая принимает два параметра: функцию обратного вызова (коллбек) и время, определенное в милисекундах. Она откладывает выполнение полученной функции до истечения заданного времени. Если передать 1000 в качестве второго параметра, мы отложим выполнение переданной функции на 1 секунду после того, как собственно вызовем саму эту функцию.

Внутри функции контроллера первое что мы делаем, это создаем атрибут counter и устанавливаем ему значение по умолчанию 0. Мы хотим, чтобы отчет начинался с 0.

Затем мы создаем функцию updateCounter, которая при вызове будет увеличивать counter и использовать $timeout, чтобы вызвать себя же спустя 1 секунду. Это значит, что каждый раз при вызове функции updateCounter она увеличит счетчик и запланирует в системе повторный вызов через 1 секунду. Это значит, функция будет запускаться каждую секунду.

Затем последний шаг это первый вызов updateCounter для запуска бесконечного цикла.

Счетчик с кнопкой Стоп

Этот счетчик будет увеличиваться каждую секунду, но что если мы захотим остановить его? Мы увидим пример с дополнительной кнопкой, которая остановит счетчик.

$timeout возвращает объект promise, который мы можем использовать позднее, чтобы отключить таймер. Чтобы сделать promise доступным, когда нам будет нужно, я создал переменную timer и присвоил ей то, что вернула функция $timeout. (Конечно, я мог бы использовать здесь любое другое имя.)

Затем я добавил кнопку в HTML и указал в атрибуте ng-click вызов метода stopCounter.

Осталось сделать только метод stopCounter.

Для начала я создал его, используя var stopCounter = function() { ... } как и updateCounter, но это не сработало. Так как мы хотим вызывать метод из HTML, нам нужно добавить этот метод в $scope. Следовательно, я должен был заменить определение на: $scope.stopCounter = function() { ... }.

Внутри у нас есть выражение $timeout.cancel(timer);, которое отменит работу таймера. Попробуйте!

examples/angular/automatic_counter_with_stop.html

<script src="angular.min.js"></script>
<script>
angular.module('CounterApp', [])
    .controller('CounterController', function($scope, $timeout) {
        var timer;
        $scope.counter = 0;
        $scope.stopCounter = function() {
            $timeout.cancel(timer);
        };
        var updateCounter = function() {
            $scope.counter++;
            timer = $timeout(updateCounter, 1000);
        };
        updateCounter();
    });
</script>
<div ng-app="CounterApp">
   <div ng-controller="CounterController">
   {{counter}}
   <button ng-click="stopCounter()">Stop</button>
   </div>
</div>
Try!

Счетчик с кнопками запуска и остановки

Еще одна штука, которую я хочу показать, это как я добавил еще одну кнопку для запуска счетчика дальше.

Первая версия была простой. Я просто добавил кнопку и новую функцию:

$scope.startCounter = function() {
    updateCounter();
};

Проблема такого решения в том, что оно позволяло мне нажать несколько раз на кнопку старта, и счетчик начинал увеличиваться слишком быстро, перескакивая иногда на 2 или 3 шага. В реальности происходило вот что: каждый раз, когда я нажимал на кнопку start, запускался новый таймер и несколько таймеров работало параллельно.

Я должен был как-то убедиться, что в одно время работает только один таймер. Либо заблокировать кнопку start после нажатия, либо проверять, что таймер уже запущен, и запускать новый только если это не так.

Я выбрал это решение, так как был больше заинтересован в решении на JavaScript/AngularJS. Я сделал два изменения. В функции stopCounter я добавил

timer = null;

В конце концов все что у нас есть, это отмененный таймер, и нет смысла держать неиспользуемые объекты.

Затем в методе startCounter я смог проверить, является ли timer null или нет, и создать новый объект $timeout, если таймер отсутствует.

examples/angular/automatic_counter_with_stop_start.html

<script src="angular.min.js"></script>
<script>
angular.module('CounterApp', [])
    .controller('CounterController', function($scope, $timeout) {
        var timer;
        $scope.counter = 0;
        $scope.stopCounter = function() {
            $timeout.cancel(timer);
            timer = null;
        };
        $scope.startCounter = function() {
            if (timer === null) {
                updateCounter();
            }
        };
        var updateCounter = function() {
            $scope.counter++;
            timer = $timeout(updateCounter, 1000);
        };
        updateCounter();
    });
</script>
<div ng-app="CounterApp">
   <div ng-controller="CounterController">
   {{counter}}
   <button ng-click="stopCounter()">Stop</button>
   <button ng-click="startCounter()">Start</button>
   </div>
</div>
Try!

Savenkova Natalya
Переводчик
Savenkova Natalya
Gabor Szabo
Автор
Gabor Szabo

Comments