6、驯服线程和定时器

定时器和线程是如何工作的

JavaScript提供了两种方式,用于创建定时器以及两个相应的清除方法。这些方法都是window对象上的。

// 在一段时间(delay)之后执行传入的fn方法,并返回该定时器的唯一标识
id=setTimeout(fn,delay);
// 在定时器还未触发时,取消定时器
clearTimeout(id)

// 在每间隔一段时间(delay)之后都执行传入的fn方法,并返回该定时器的唯一标识
id=setInterval(fn,delay);
// 取消间隔定时器
id=clearInterval(id)

由于JavaScript是单线程的,在特定的时间点只能运行一个执行代码,而且也无法确定定时器处理程序到底是在什么时候执行,当一个异步事件发生时(鼠标单击,定时器触发,或者是ajax返回函数),它会进行排队,在线程空闲时才进行执行,并且每个浏览器的排队机制是不同的,浏览器不会对来自同一个setInterval()的多个回调进行排队,同一时刻,将只会有一个来自同一setInterval()的回调在队列中。
interval间隔定时器并不是周期执行的timeout定时器,通过下面代码可以看出差异。

setTimeout(function repeat() {
    /*主内容代码*/
    setTimeout(repeat,10);
},10);

setInterval(function () {
    /*主内容代码*/
},10);

在setTimeout()代码中,要在前一个主题内容代码执行结束并延迟10ms的时间后,才能再次执行setTimeout()。
而setInterval()代码中,每间隔10ms就尝试执行主内容代码,并不会关注上一次setInterval()中的主内容代码是如何执行的。
浏览器无法保证我们制定的延迟间隔,尤其是在间隔时间非常小的情况下,因为执行回调函数和代码本身也要花费时间。

处理昂贵的计算过程

下面代码会创建240000个DOM节点,并使用大量单元格来填充一个表格。

var tbody = document.getElementsByTagName("tbody")[0];
for(var i=0;i<20000;i++){
    var tr = document.createElement("tr");
    for(var j=0;j<6;j++){
        var td = document.createElement("td");
        td.appendChild(document.createTextNode(i+","+j));
        tr.appendChild(td);
    }
    tbody.appendChild(tr);
}

执行类似上述计算昂贵的代码,浏览器往往会卡顿很长时间,将这些操作分隔,定期让代码中断,并记录中断的地方,间隔一定时间再调度下一阶段。

var row = 20000;
var divede = 10;  // 分隔的数量
var cur = row / divede;  // 每次执行的次数
var now = 0;  // 执行的阶段
var tbody = document.getElementsByTagName("tbody")[0];
setTimeout(function goNow() {
    var go = cur * now;  // 记录上次中断结束的地方
    for(var i=0;i<cur;i++){
        var tr = document.createElement("tr");
        for(var j=0;j<6;j++){
            var td = document.createElement("td");
            td.appendChild(document.createTextNode((i+go)+","+j+","+now));
            tr.appendChild(td);
        }
        tbody.appendChild(tr);
    }
    now++; // 调度下一阶段
    if(now<divede){
        setTimeout(goNow,0);
    }
},0);

中央定时器控制

var timers = {  // 定义中央定时器控制对象
    timerID:0,  // 当前正在执行的定时器,为0则表示没有定时器在执行
    timers: [],  // 保存定时器需要执行的所有回调函数
    add:function (fn) {  // 定义add方法,添加回调函数
        this.timers.push(fn);
    },
    start:function (time) {  // 执行定时器
        if(this.timerID) return;  // 没有定时器时,执行一个即时函数来开启中央定时器
        (function runNext() {  // 执行当前定时器
            if(timers.timers.length>0){  // 遍历所有回调函数进行执行
                for(var i=0;i<timers.timers.length;i++){
                    if(timers.timers[i]()===false){  // 当某个回调函数不需要在执行时,将其删除
                        timers.timers.splice(i,1);
                        i--;
                    }
                }
                timers.timerID = setTimeout(runNext,time); // 等待time时间再次调用定时器
            }
        })();
    },
    stop:function () {  // 清除定时器
        clearTimeout(this.timerID);
        this.timerID =0;
    }
};

// 测试中央控制器
var box = document.getElementById("box"),x=0,y=0;
timers.add(function () {
    box.style.left=x+"px";
    if((x+=1)>200)return false;
});
timers.add(function () {
    box.style.top=y+"px";
    if((y+=1)>200)return false;
});
timers.start(10);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 9.26-9.30 第8章 驯服线程和定时器 定时器可以在js中使用,但它不是js的一项功能,如果我们在非浏览器环...
    如201608阅读 583评论 0 2
  • 一、什么是定时器 JS提供了一些原生方法来实现延时去执行某一段代码,下面来简单介绍一下 setTimeout: 设...
    SSSSSSH阅读 929评论 1 50
  • 从JS执行机制说起 浏览器(或者说JS引擎)执行JS的机制是基于事件循环。 由于JS是单线程,所以同一时间只能执行...
    love2013阅读 865评论 0 1
  • 定时器并不属于JavaScript 虽然我们一直在JavaScript中使用定时器,但是它并不是javascrip...
    打铁大师阅读 857评论 0 4
  • 在谈js定时器以前,我觉得有必要了解下javascript的事件运行机制,简称(javascript event ...
    JohnsonChe阅读 896评论 0 2