Javascript: как запустить код по таймеру из метода класса
Представим, что хотим запускать функцию класса Javascript по таймеру с помощью setTimeout
или setInterval
.
Увы, казалось бы, естественное
this.timerId = setTimeout(function () { this.doTimer (); }, this.timeInterval);
написанное в другом методе класса, к успеху не приведёт, лишь будем получать с периодом таймера ошибку
Uncaught TypeError: this.doTimer is not a function
Такие вещи способны свести с ума, если не знать, что помогает простое "клонирование" this
:
let that = this; //Без такого клонирования ссылки не работает setTimeout из класса this.timerId = setTimeout(function () { that.doTimer (); }, this.timeInterval);
Ссылки на свойства, такие как this.timeInterval
, можно оставить без изменений.
Обратите внимание, что приведённый ниже код (документ HTML без обрамления, кодировка Юникода UTF-8) ровно 100 шагов делать отнюдь не обязан, с измерениями малых интервалов времени у JS тоже бывают проблемы. К тому же, когда вкладка перестаёт быть активной, современные браузеры практически перестают выполнять в ней код, вызываемый по таймеру.
<div id="counter"></div> <script> class Class { constructor (id, steps, ms) { //id элемента, количество шагов, время шага в мс this.id = id; this.elem = document.getElementById (id); if (!this.elem) { console.error ('Class: Item with id='+id+' not found'); } let Steps = parseInt (steps); if (isNaN(Steps) || Steps < 1) { console.error ('Class: steps is not a positive number'); } let Ms = parseInt (ms); if (isNaN(Ms) || Ms < 1) { console.error ('Class: ms is not a positive number'); } let dt = new Date(); this.startTime = dt.getTime(); this.endTime = this.startTime + Steps*Ms; this.timeInterval = Ms; this.cnt = 0; } run () { this.doTimer (); } doTimer () { let dt = new Date(); let currentTime = dt.getTime(); if (currentTime < this.endTime) { this.cnt++; this.elem.innerHTML = this.cnt; let that = this; //Без такого клонирования ссылки не работает setTimeout из класса this.timerId = setTimeout(function () { that.doTimer (); }, this.timeInterval); } else { clearInterval(this.timerId); } } } let timer = new Class ('counter', 100, 100); timer.run(); </script> <noscript><p>Нужен Javascript для работы приложения!</p></noscript>
10.02.2021, 19:19 [1020 просмотров]