微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

你会用setTimeout吗

2016-03-27 20:53 前端大全

(点击上方,可快速关注)


作者:唐光尧

网址:http://tangguangyao.github.io/2015/11/10/%E4%BD%A0%E4%BC%9A%E7%94%A8setTimeout%E5%90%97/


教科书里面的setTimeout


定义很简单


setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。


广泛应用场景


定时器,轮播图,动画效果,自动滚动等等


上面一些应该是setTimeout在大家心中的样子,因为我们平常使用也不是很多。


但是setTimeout真的有那么简单吗?


测试题


一个题目,如果你在一段代码中发现下面内容


var startTime = new Date();

setTimeout(function () {

    console.log(new Date() - startTime);

}, 100)


请问最后打印的是多少?


我觉得正确答案是,取决于后面同步执行的js需要占用多少时间。

MAX(同步执行的时间, 100)。


再加一个题目,只有下面代码


setTimeout(function () {

    func1();

}, 0)

func2();


func1和func2谁会先执行?


这个答案应该比较简单,func2先执行,func1后面执行。


再来一题


setTimeout(function () {

    func1()

}, 0)



setTimeout(function () {

    func1()

})


有什么差别?


0秒延迟,此回调将会放到一个能立即执行的时段进行触发。javascript代码大体上是自顶向下的,但中间穿插着有关DOM渲染,事件回应等异步代码,他们将组成一个队列,零秒延迟将会实现插队操作。

不写第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。


上面答案来自《javascript框架设计》


好了,看了上面几个题目是不是感觉setTimeout不是想象中那样了。


setTimeout和单线程


下面是我自己的一些理解


首先需要注意javascript是单线程的,特点就是容易出现阻塞。如果一段程序处理时间很长,很容易导致整个页面hold住。什么交互都处理不了怎么办?


简化复杂度?复杂逻辑后端处理?html5的多线程?


上面都是ok的做法,但是setTimeout也是处理这种问题的一把好手。


setTimeout一个很关键的用法就是分片,如果一段程序过大,我们可以拆分成若干细小的块。


例如上面的情况,我们将那一段复杂的逻辑拆分处理,分片塞入队列。这样即使在复杂程序没有处理完时,我们操作页面,也是能得到即使响应的。其实就是将交互插入到了复杂程序中执行。


换一种思路,上面就是利用setTimeout实现一种伪多线程的概念。


有个函数库Concurrent.Thread.js 就是实现js的多线程的。


一个简单使用的例子,引入Concurrent.Thread.js后


Concurrent.Thread.create(function(){

    for (var i = 0;i<1000000;i++) {

        console.log(i);

    };

});

$('#test').click(function  () {

    alert(1);

});


虽然有个巨大的循环,但是这时不妨碍你去触发alert();


是不是很厉害~


还有一种场景,当我们需要渲染一个很复杂的DOM时,例如table组件,复杂的构图等等,假如整个过程需要3s,我们是等待完全处理完成在呈现,还是使用一个setTimeout分片,将内容一片一片的断续呈现。


其实setTimeout给了我们很多优化交互的空间。


如何使用


setTimeout这么厉害,那么我们是需要在在项目中大量使用吗?


我这边的观点是非常不建议,在我们业务中,基本上是禁止在业务逻辑中使用setTimeout的,因为我所看到的很多使用方式都是一些问题不好解决,setTimeout作为一个hack的方式。


例如,当一个实例还没有初始化的前,我们就使用这个实例,错误的解决办法是使用实例时加个setTimeout,确保实例先初始化。


为什么错误?这里其实就是使用hack的手段


第一是埋下了坑,打乱模块的生命周期

第二是出现问题时,setTimeout其实是很难调试的。


我认为正确的使用方式是,看看生命周期(可参考《关于软件的生命周期 》),把实例化提到使用前执行。


综上,setTimeout其实想用好还是很困难的, 他更多的出现是在框架和类库中,例如一些实现Promis的框架,就用上了setTimeout去实现异步。

所以假如你想去阅读一些源码,想去造一些轮子,setTimeout还是必不可少的工具。



【今日微信公号推荐↓】

更多推荐请看值得关注的技术和设计公众号


其中推荐了包括技术设计极客 和 IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!


点击“阅读原文”,了解详情。

 
前端大全 更多文章 详解Javascript中的Object对象 结合个人经历总结的前端入门方法 前端不为人知的一面–前端冷知识集锦 一份优秀的前端开发工程师简历是怎么样的? 浅谈Web缓存
猜您喜欢 开源Web视频监控系统 ZoneMinder Linux服务器——Google二次验证登陆 Android Binder 全解析(三) 10倍提升应用性能的10个建议 PyTips 0x0b - Python 无处不在的 else