1

高级定时器

为了解决setInterval的一些执行问题, 下面是采用链式setTimeout的方式来规避:

setTimeout(function() {
    // add code here
    setTimeout(arguments.callee, interval);
}, interval);

避免使用arguments.callee:

setTimeout(function func () {
    // body...
    setTimeout(func, interval);
}, interval);

Yielding Processes

脚本长时间运行的原因: 过长的、 过深嵌套的函数调用; 进行大量的处理循环。
在展开循环之前, 你需要考虑两个重要的问题:

  1. 该出事是否必须同步完成?

  2. 数据是否必须按顺序完成?

当你发现有些循环占用大量的事件, 同时对上述两个问题答案都是否, 那么可以使用定时器来分隔这个循环。

setTimeout(function() {
    //取出下一个条目处理
    var item = array.shift();
    process(item);
    //还有条目,再设置一个定时器
    if (array.length > 0) {
        setTimeout(arguments.callee, interval);
    }
}, interval);

如:

var div = document.getElementById("div");
var arr = [321, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31, 32, 1432, 432, 432, 321, 5435, 6454, 6576, 56434, 2321, 321, 31];

for (var i = 0, len = arr.length; i < len; i++) {
    div.innerHTML += arr[i] + "<br/>";
};
//16ms 用时

setTimeout(function shiftArr() {
    var item = arr.shift();
    div.innerHTML += item + "<br/>";
    if (arr.length > 0) {
        setTimeout(shiftArr, 0);
    }
}, 0)
//58.2ms 用时

函数节流

对一些持续不断触发的事件, 如果建立的事件处理程序不够好的话, 会导致浏览器崩溃或者其他的事故。 为了规避这个问题, 可以使用定时器对事件处理程序进行节流。

函数节流背后的基本思想是: 一些代码不可以在没有间断的情况下连续重复执行。 具体做法是: 第一次调用函数, 创建一个定时器, 在指定的时间间隔后运行代码。 当第二次调用该函数时, 它会清除前一次的定时器, 并设置另一个。 如果前一个定时器已经执行过了, 这个操作就没有任何意义。 然而如果前一个定时器尚未执行, 其实就是将其替换为一个新的定时器。 目的就是执行函数的请求停止了一段时间之后才执行。 以下是该模式的基本形式:

var processor = {
    timeoutId: null,

    performProcessing: function() {
        //实际执行的处理程序
    },
    process: function() {
        clearTimeout(this.timeoutId);
        var that = this;
        this.timeoutId = setTimeout(function() {
            that.performProcessing();

        }, 1000);
    }
};
processor.process(); //尝试开始执行

只要代码是周期性执行的, 都应该用节流。 处理的速率根据需求设置, 上面的例子是1000毫秒。


JS菌
6.4k 声望2k 粉丝