资讯专栏INFORMATION COLUMN

你真会用setTimeout吗?

jsyzchen / 3193人阅读

摘要:什么交互都处理不了怎么办简化复杂度复杂逻辑后端处理的多线程上面都是的做法,但是也是处理这种问题的一把好手。换一种思路,上面就是利用实现一种伪多线程的概念。

教科书里面的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还是必不可少的工具。

微信公众号

博客地址

http://tangguangyao.github.io/

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86185.html

相关文章

  • 线程池你真不来了解一下

    摘要:所以说我们的线程最好是交由线程池来管理,这样可以减少对线程生命周期的管理,一定程度上提高性能。线程池不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。当所有的任务已终止,记录的任务数量为,线程池会变为状态。线程池彻底终止的状态。 前言 只有光头才能变强 回顾前面: ThreadLocal就是这么简单 多线程三分钟就可以入个门了! 多线程基础必要知识点!看了学习多线程事半功倍...

    stdying 评论0 收藏0
  • 前端er,你真会用 async

    摘要:异步函数是值通过事件循环异步执行的函数,它会通过一个隐式的返回其结果。 async 异步函数 不完全使用攻略 前言 现在已经到 8012 年的尾声了,前端各方面的技术发展也层出不穷,VueConf TO 2018 大会 也发布了 Vue 3.0的计划。而在我们(我)的日常中也经常用 Vue 来编写一些项目。那么,就少不了 ES6 的登场了。那么话说回来,你真的会用 ES6 的 asyn...

    Jaden 评论0 收藏0
  • 笑出腹肌!有些程序员真会玩代码注释

    摘要:转自网络,部分出自网友这是一个被代码耽误的诗人来一份年的代码看看产品经理要对此负责不敢看,也不敢问官网上的注释程序员正确发牢骚的地方阅读源码的人,心里一定的崩溃的第一天上班看到这段注释就想辞职。 转自网络,部分出自 Quora 网友 0、这是一个被代码耽误的诗人 1、来一份 19...

    tinyq 评论0 收藏0
  • 易探云:“夏日炎炎,有你真甜”活动,香港/韩国/美国/深圳云服务器优惠活动

    易探云怎么样?易探云8月份上线夏日炎炎,有你真甜活动,降价,降价,给云服务器降价降温了!购买易探云服务器月付送QQ音乐豪华版绿钻1月及云服务器年付送QQ音乐绿钻豪华版1年,而且给云服务器四大惊喜,年付低至6折起!香港CN2(荐)可用区1核1G2M云服务器月付仅18元/月(首月优惠),年付低至238元/年起;韩国cn2云服务器2核2G2M20G配置仅548元/年;美国bgp云服务器2核2G5M20G...

    番茄西红柿 评论0 收藏2637
  • 你真会用 Babel ?

    摘要:安装然后在的配置文件加入入口文件引入这样就可以啦,还是可以减少很多代码量的。是参数,等同于执行正常。这个包很简单,就是引用了和,然后生产环境把它们编译到目录下,做了映射,供使用。 引入 这个问题是对自己的发问,但我相信会有很多跟我一样的同学。对于 babel 的使用,近半年来一直停留在与 webpack 结合使用,以及在浏览器开发环境下。导致很多 babel 的包,我都不清楚他们是干嘛...

    mochixuan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<