关于javascript:clearTimeout偶尔会失败

clearTimeout fails sporadically

我正在尝试在Angular 2环境中管理计时器,而clearTimeout似乎只能正常工作大约一半的时间。 我正在用TypeScript编写。

我将计时器保留在自己的服务中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
export class TimeoutService {
    constructor(
        private router: Router,
        private httpService: HttpService
    ) {}

    //Properties
    private timer;

    //Methods
    public clearTimer() {
        clearTimeout(this.timer);
    }

    private logOut() {
        return this.httpService.Post('api/session/logout', '');
    }

    private redirectToTimeoutPage() {
        this.router.navigate(['/timeout']);
    }

    public refreshTimer() {
        console.log('refreshing timer');

        if (this.timer) {
            this.clearTimer();
            this.setTimer();
        }
    }

    public startTimer() {
        this.setTimer();
    }

    private setTimer() {
        this.timer = setTimeout(() => {
            this.logOut()
                .then(() => {
                    this.clearTimer();
                    this.redirectToTimeoutPage();
                });
        }, 30000);
    }
}

我从refreshTimer方法的console.log中知道,它在我期望的时候被调用,否则就不会被调用。 但是,在大多数情况下,较早的计时器不会被clearTimeout调用取消,并且会在三十秒结束后立即触发,即使它们应该已被新的计时器替换。

我已经解决了其他有关此的问题,据我所知,没有一个问题适用于我的情况。

我无法理解的一个提示是,如果我在refreshTimer中删除了对this.setTimer()的调用,那么clearTimeout调用似乎可以正常工作。 换句话说,创建新计时器会以某种方式使旧计时器存活下来。 我在这里想念什么?

谢谢!


refreshTimer中,您需要在调用this.setTimer()之前先调用this.clearTimer()

但是,在startTimer中,您不会调用this.clearTimer()。因此,如果调用代码多次调用startTimer而不进行任何调用this.clearTimer的操作,则您将启动多个超时,但是只有最后一个会被您的类记住并在this.clearTimer被取消时被取消。再次打电话。


clearTimeout函数中,您不仅要清除计时器,还想重置timer变量:

1
2
3
4
public clearTimer() {
    clearTimeout(this.timer);
    this.timer = null; // <-- You also want your variable to become null here.
}

然后,在调用clearTimer()之后运行的任何代码都将正确地将timer变量评估为null,这正确指示不存在计时器。对于包装器而言,仅停止运行计时器是不够的。

同样(FYI),正如我在评论中说的那样,这是初始化所有变量的一种很好的最佳实践,这样就不会出现"意外"值。

1
 private timer;

应该:

1
 private timer = null;


我会将对clearTimer的调用移到setTimer函数中,看看是否有帮助。