Задать вопрос
@tryvols
Front-End разработчик

Почему не работает clearTimeout?

Казалось бы все ок, в месте вызова this._timeoutId актуальный, но таймер не замолкает при вызове disable...

import { injectable } from 'inversify';
import { TimerCallback, ITimer, DelayCalculator } from '../types/timer';

@injectable()
export default class Timer implements ITimer {
    private _startDelay: number;
    private _timeoutId: number;

    constructor(
        private _delay: number,
        private _nextDelay: DelayCalculator,
        private _callback?: TimerCallback,
    ) {
        this._startDelay = _delay;
    }

    public setCallback = (callback: TimerCallback): void => {
        this._callback = callback;
    }

    public enable = (): void => {
        if (!this._callback) {
            throw Error('Callback is required for the Timer!');
        }

        this._tick();
    }

    public disable = (): void => {
        if (!this._timeoutId) {
            console.warn('You trying to disable timer which is not enabled.');
            return;
        }
        clearTimeout(this._timeoutId);
        delete this._timeoutId;
    }

    public reset = (): void => {
        this._delay = this._startDelay;
    }

    private _tick = (): void => {
        this._timeoutId = setTimeout(() => {
            this._callback();
            this._delay = this._nextDelay(this._delay);
            this._tick();
        }, this._delay);
    }
}
  • Вопрос задан
  • 129 просмотров
Подписаться 1 Средний 2 комментария
Пригласить эксперта
Ответы на вопрос 2
Тоже не могу понять, но у меня какие-то смутные сомнения из-за ваших стрелочных функций в качестве членов класса, хотя вроде это вполне законно. А если потрейсить this._timeoutId перед clearTimeout(this._timeoutId); ? Вдруг он null?
Ответ написан
@tryvols Автор вопроса
Front-End разработчик
Почему так происходит я не разобрался, но решением стало изменение подхода. Заюзал асинхронщину)

export function delay<T>(ms: number, value?: T): Promise<T> {
    return new Promise((resolve) => setTimeout(() => resolve(value), ms));
}


import { injectable } from 'inversify';
import { TimerCallback, ITimer, DelayCalculator } from '../types/timer';
import { delay } from '../../../helpers/delay';

@injectable()
export default class Timer implements ITimer {
    private readonly _startDelay: number;
    private _enable: boolean;
    private counter: number = 0;

    constructor(
        private _delay: number,
        private _nextDelay: DelayCalculator,
        private _callback?: TimerCallback,
    ) {
        this._startDelay = _delay;
    }

    public setCallback = (callback: TimerCallback): void => {
        this._callback = callback;
    }

    public enable = (): void => {
        if (!this._callback) {
            throw Error('Callback is required for the Timer!');
        }

        this._enable = true;
        this._tick();
    }

    public disable = (): void => {
        if (!this._enable) {
            console.warn('You trying to disable timer which is not enabled.');
            return;
        }
        this._enable = false;
    }

    public reset = (): void => {
        this.disable();
        this._delay = this._startDelay;
    }

    private _tick = async (): Promise<void> => {
        await delay(this._delay);
        if (this._enable) {
            this._callback();
            this._delay = this._nextDelay(this._delay);
            await this._tick();
        }
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы