你真会用setTimeout吗?

教科书里面的setTimeout

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

普遍应用场景
定时器,轮播图,动画效果,自动滚动等等html

上面一些应该是setTimeout在你们心中的样子,由于咱们日常使用也不是不少。html5

可是setTimeout真的有那么简单吗? java

测试题git

一个题目,若是你在一段代码中发现下面内容github

var startTime = new Date();
    setTimeout(function () {
        console.log(new Date() - startTime);
    }, 100)

请问最后打印的是多少?
我以为正确答案是,取决于后面同步执行的js须要占用多少时间。
MAX(同步执行的时间, 100)chrome

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

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仍是必不可少的工具。

微信公众号

图片描述

博客地址

http://tangguangyao.github.io/

相关文章
相关标签/搜索