JavaScript定时器:setTimeout与setInterval 定时器与异步循环数组

深入了解一下 关于JavaScript定时器的知识;

setTimeout与setInterval简述

setTimeout与setInterval使用方法基本相同,他们接受两个参数,第一个参数是需要执行的函数,第二个参数是执行的延迟时间,看栗子:

setTimeout(function(){   
    alert("hello");  //第一个参数为函数 你可以传入函数名 或一个匿名函数
   },3000);     //第二个参数为延迟时间  标识多少毫秒之后执行前一个函数
   setInterval(function(){   
    alert("hello");   
},3000);

setTimeout与setInterval唯一不同的是,setTimeout在指定的延迟时间到达后 向ui队列添加一个任务,函数会立即执行,setInterval则是在指定的延迟时间不断的向ui队列添加执行任务,如果你没有手动清除那么setInterval就会一直执行下去,直到页面被关闭,如果ui队列中存在由同一个setInterval创建的任务,那么后续任务将不会被添加到ui队列中。

通俗的说就是,让一个函数在指定时间之后再执行,和让一个函数在指定时间一直执行;

然而它在实际项目中有什么作用呢,我们可以利用setInterval制作定时幻灯片、实时数据更新、新闻列表滚动、jQuery的.animate()方法就是依靠定时器模拟动画效果;此博客实现了这一代码,贴在下面与大家一起讨论: http://www.cnblogs.com/slowsoul/archive/2013/02/21/2921354.html JavaScript——创建运动框架

提到定时器,就不得不先介绍一个JavaScript运行机制--》浏览器UI线程

用于执行javascript和更新用户界面的进程通常被称为“浏览器UI线程”

在浏览器中,Javascript执行与UI更新是发生在同一个进程(浏览器UI线程)中的。UI线程的工作基于一个简单的队列系统,任务会被保存到队列 中直到进程空闲时被提取出来执行。所以Javascript的执行会阻塞UI更新;反之,UI更新也会阻塞Javascript的执行。给用户的表现就是 浏览器在工作时短暂或长时间失去反应,用户的操作不能及时得到响应。而UI线程的阻塞很多时候是由于我们要在代码里进行长时间的脚本运算,超过了浏览器限 制,导致浏览器失去响应,冻结用户界面。传送门: Javascript之UI线程与性能优化

使用定时器可以异步处理需要大量运算的任务,它可以适时的避免ui更新与javascript执行之间的冲突

例如在某种极端环境下:

for(var i=0;i<5000;i++){   
    document.body.innerHTML += "hello"+i;   
}

这段代码向body插入字符串 持续运行了五千次,在谷歌浏览器中这段代码会执行3秒左右 而这段时间页面始终是空白且不可操作的,这是一个非常常见的性能问题,在处理大量运算的时候,我们可以利用延迟执行将代码分成几段分别运行,可以有效改善代码执行速度,并且因为它是异步的 在执行中的空隙,ui会启动更新,因此并不会导致页面空白,用户体验提高;

setTimeout(function(){   
    for(var i=0;i<2500;i++){   
        document.body.innerHTML += "hello"+i;   
    }   
//分段处理 五千次分成两段   
    setTimeout(function(){   
        for(var i=0;i<2500;i++){   
            document.body.innerHTML += "hello"+i;   
        }   
    },100);   
},100);

假如向服务器请求一个超长的新闻列表,由于数据量过去庞大,单个循环解析数据持续时间过长,那么可以使用定时器分解任务,异步处理数据

一般情况下,我们处理数据都是这样的:

for(var i=0,len=msg.length;i<len;i++){   
 process(msg[i])         
}

一般我们使用for或者while循环解析数据, 这样的问题是 在执行完成之前我们是没有办法控制页面的,数据越庞大越明显

使用定时器分解任务

使用定时器分解任务有两个前提

1、数据的处理不需要按照特定的顺序

2、是否必须同步处理,如果必须同步处理那么定时器不适用;

其核心理论是,每间隔一段时间(通常是30毫秒,视情况而定)执行当前项的处理函数;

封装之后的代码:

volist:function(name,id,callback,time){   
//settimeout 异步循环 name为需要循环的array对象 id为要执行的解析函数  time设置每次运行的时间   
        if(time==undefined){time=30;};   
        var fattr = name.concat();//克隆数组   
        setTimeout(function(){   
            if(fattr.length>0){   
                id(fattr.shift());  //执行每一个数组项运行的函数   
                setTimeout(arguments.callee,time);   
            }else{   
                callback();//执行结束 回调函数   
            }   
        },time);//异步调用时间  默认30    
    }

还有另一种使用方式,将函数放在数组里,异步循环调用,将要执行的多个任务拆分成不同的子任务,分阶段分别执行:

function fun1(){   
    alert(1)   
}   
function fun2(){   
    alert(2)   
}   
function fun3(){   
    alert(3)   
}   

var farr = [fun1,fun2,fun3];  //将任务存储到数组中   

setTimeout(function(){   

    if(farr.length>0){   

        var func=farr.shift();  //取出   
               func(); //执行函数   
        setTimeout(arguments.callee,300);   
    }else{   
        alert("执行完成")   
    }   

},300);      //300秒执行一次

定时器的性能问题

需要注意的是,当一个页面中存在多个定时器,他们执行的任务过多,往往会导致不可预料的问题;解决方法就是尽量避免创建多个定时器,只创建一个独立的定时器,让它分别执行不同的任务,另外每次调用setInterval()之前应清除前面已经无用的setInterval,或者是防止重复指定setInterval

var timer   
//先清除   clearInterval(timer);   
//再调用   
  timer = setInterval(function(){   
    ......   
},5000);

总结

合理使用定时器无疑能够增加页面的整体性能,在处理不需要同步,不需要顺序执行的任务时,可以考虑使用setTimeout代替for循环 异步处理任务;

原文发布于微信公众号 - 交互设计前端开发与后端程序设计(interaction_Designer)

原文发表时间:2016-08-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android自学

给WordPress文章添加类似说说的状态样式

20630
来自专栏一“技”之长

OS X 开发:打开文件面板NSOpenPanel应用

      在Mac桌面软件开发中,如果涉及到对文件的操作,无论是新建文件还是选择或读取文件,都离不开文件路径的定位,NSOpenPanel类提供了简洁的文件选...

14030
来自专栏逍遥剑客的游戏开发

Nebula3的渲染线程插件(Render Thread Plugin)

15840
来自专栏Golang语言社区

golang文件传输服务

本篇介绍一个完整的golang文件传输服务器。 完整的代码可以看服务器,客户端 网络使用的框架如上篇介绍,这里就不再复述. 首先定义3个命令码: const (...

41050
来自专栏吴裕超

js设计模式之惰性单例模式

<html> <body> <button id="loginBtn">登录</button> </body> <script> var cr...

38960
来自专栏布尔

Ext的组件模型印象

组件模型在Ext1.x中已经引入了,但在框架中并没有得到全面的整合。2.0以后组件得到了很大的提高和改进,成为了框架的里最基础的一个类。组件对象模型为组件的创建...

193100
来自专栏偏前端工程师的驿站

location的hash部分和使用window.onhashchange实现ajax请求内容时使用浏览器后退和前进功能

 在js跨域双向数据传递时可以用iframe加上location.hash来实现,在研究这个的时候深入学习了一下hash的特性。   hash就是uri中#及后...

251100
来自专栏我爱编程

Day22psutil&图形界面

psutil 用Python来编写脚本简化日常的运维工作是Python的一个重要用途。 在Python中获取系统信息的一个好办法是使用psutil这个第三方模...

29550
来自专栏deepcc

判断IE版本的语句 [if lte IE 6]...[endif]

40270
来自专栏Core Net

C# 处理Word自动生成报告 三、设计模板

53050

扫码关注云+社区

领取腾讯云代金券