最近在做用setInterval在做定时器的时候,发现一些问题。

就是一旦定时器中一旦任务执行时间超过定时间隔时间得时候,JavaScript不会等待这次任务执行完毕,重现计算时间间隔,而是到时间间隔一到立马将下次任务加入队列,并且等待该次任务执行完毕后,立马执行,所有定时加载变成循环加载。这是我们所不愿意见到的。

setInterval代码:

function startFn2() {
       var p2 = new AlarmClockByInterval(callBackByTest, 2000);
}
function callBackByTest() {
    var i = 0;
    for (; i < 900000000; i++) {

    }
    return true;
}
function AlarmClockByInterval(_args1, _args2) {
    var timeFn, self = this,
        callBackFn = _args1,
        ms = _args2,
        i = 0;
    this.getInterval = function() {
        if (ms) {
            if (!timeFn) {
                timeFn = setInterval(function() {

                    console.log("定时任务开始执行:"+new Date().getTime());
                    callBackFn();
                    console.log("定时任务结束执行:"+new Date().getTime());
                    
                }, ms);
            }
        } else {
            closeInterval();
        }

    }
    this.closeInterval = function() {
        if (timeFn) {
            clearInterval(timeFn);
        }
    }
    self.getInterval();

}

wKiom1Z6dhmhhy5XAABKJcZDauc152.png

大家可以看到,定时任务一旦执行完毕,立马进行下一次任务,并没有理想中的间隔。

任务执行时间也被计算到间隔时间了。直接用setInterval并不能获得我们理想中的效果。

解决:

使用setTimeOut,和递归,利用函数自动调用自身,很延时执行就可以很好的解决这个问题。

function AlarmClockByTimeOut(_args1, _args2) {
    var _type = 0,
        timeFn, _flag = true,
        ms = _args2,
        callBackFn = _args1,
        self = this;
    this.getTimeOut = function() {
        var _callee = arguments.callee;
        if (_flag) { //内部错误,内部强制中断,终止递归
            if (_type == 0) { //外部终止递归
                timeFn = setTimeout(function() {
                    console.log("定时任务开始执行:"+new Date().getTime());
                    _flag = callBackFn();
                    console.log("定时任务结束执行:"+new Date().getTime());
                    _callee();
                }, ms);
            } else {
                if (timeFn) clearTimeout(timeFn);
                console.error(500, "定时器已终止,外部终止...");
            }
        } else {
            if (timeFn) clearTimeout(timeFn);
            console.error(500, "定时器已终止,回调函数出现错误或内部强制终止...");
        }
    };
    this.close = function(_args1) {
        _type = _args1 || 1;
    };
    self.getTimeOut();
}
function startFn2() {
    var p1 = new AlarmClockByTimeOut(callBackByTest,1000);

    // var p2 = new AlarmClockByInterval(callBackByTest, 2000);
}

执行效果:

wKioL1Z6d9-QrBqsAABa2wJuz8Y700.png

这样每次执行完成都会等1000ms,才去加载下一次任务。第一次写博客,有啥问题欢迎讨论