• setTimeout的核心原理和巧用


    你所不了解的setTimeout

    小编推荐:掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue.js,性能优化到开源类库,让你不错过前端开发的每一个技术干货。各大应用市场搜索「掘金」即可下载APP,技术干货尽在掌握..

    看到了一篇不错的文章《你会用setTimeout吗 》,转载过来的,改了个名字,一下子感觉搞大上了,嘎嘎。

    加了几个关于 setTimeout 和setInterval的小知识:

    关于setInterval()和setTimeout()返回值

    setInterval(),setTimeout() 会返回一个值,一般认为是ID,将这个ID值传递给clearInterval(),clearTimeout() 可以取消执行,例如:

    js 代码:
    1. var intervalTimer=setInterval(function(){
    2. console.log(1)
    3. },3000);
    4. console.log(intervalTimer); //一般是一个数字,Number
    5. button.onclick=function(){
    6. clearInterval(intervalTimer);
    7. };

    关于setInterval()和setTimeout()中回调函数中的this

    setInterval(),setTimeout() 方法是浏览器 window 对象提供,所以第一个参数函数中的this指向window对象,这跟变量的作用域有关:

    js 代码:
    var a=1;
    1. var obj={
    2. a:2,
    3. b:function(){
    4. setTimeout(function(){
    5. console.log(this.a);//这里返回的是:1;
    6. },2000);
    7. }
    8. };
    9. obj.b();

    当然你可以通过使用bind()方法来改变这个情况:

    js 代码:
    1. var a=1;
    2. var obj={
    3. a:2,
    4. b:function(){
    5. setTimeout(function(){
    6. console.log(this.a);//这里返回的是:2;
    7. }.bind(this),2000);//注意这行
    8.  
    9. }
    10. };
    11. obj.b();

    关于bind()方法,你可以看这里:http://www.css88.com/archives/5611

    关于setInterval()和setTimeout()的参数

    大家都知道setInterval()和setTimeout()可以接收两个参数,第一个参数是需要回调的函数,必须传入的参数,第二个参数是时间间隔,毫秒数,可以省略,这个可以看文章的下面,

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

    但是我要说的当然不是这个,我要说的是setInterval()和setTimeout()可以接收更多的参数,那么这些参数是干什么用的呢?从第三个参数开始,依次用来表示第一个参数(回调函数)传入的参数,例如:

    js 代码:
    1. setTimeout(function(a,b){
    2. console.log(1+a+b);//这里打印的是:8
    3. },1000,3,4);

    当然一些古老的浏览器是不支持的。

    关于clearInterval()和clearTimeout()

    clearInterval()和clearTimeout()其实是通用的,就是说你可以用 clearInterval() 取消 setTimeout() 执行,clearTimeout()同样可以取消 setInterval() 执行。

    js 代码:
    1. var intervalTimer=setInterval(function(){
    2. console.log(1)
    3. },3000);
    4. console.log(intervalTimer);
    5. button.onclick=function(){
    6. clearTimeout(intervalTimer); //注意这里,不是clearInterval哦
    7. };

    =============== 以下内容来源: 你会用setTimeout吗  ===================

    教科书里面的setTimeout

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

    广泛应用场景
    定时器,轮播图,动画效果,自动滚动等等

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

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

    测试题

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

    js 代码:
    1. var startTime = new Date();
    2. setTimeout(function () {
    3. console.log(new Date() - startTime);
    4. }, 100)

    请问最后打印的是多少?
    我觉得正确答案是,取决于后面同步执行的js需要占用多少时间。
    MIN(同步执行的时间, 100)

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

    js 代码:
    1. setTimeout(function () {
    2. func1();
    3. }, 0)
    4. func2();

    func1和func2谁会先执行?

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

    再来一题

    js 代码:
    1. setTimeout(function () {
    2. func1()
    3. }, 0)

     

    js 代码:
    1. setTimeout(function () {
    2. func1()
    3. })

    有什么差别?

    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

    js 代码:
    1. Concurrent.Thread.create(function(){
    2. for (var i = 0;i<1000000;i++) {
    3. console.log(i);
    4. };
    5. });
    6. $('#test').click(function () {
    7. alert(1);
    8. });

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

    是不是很厉害~

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

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

    如何使用

    setTimeout这么厉害,那么我们是需要在在项目中大量使用吗?
    我这边的观点是非常不建议,在我们业务中,基本上是禁止在业务逻辑中使用setTimeout的,因为我所看到的很多使用方式都是一些问题不好解决,setTimeout作为一个hack的方式。
    例如,当一个实例还没有初始化的前,我们就使用这个实例,错误的解决办法是使用实例时加个setTimeout,确保实例先初始化。
    为什么错误?这里其实就是使用hack的手段
    第一是埋下了坑,打乱模块的生命周期
    第二是出现问题时,setTimeout其实是很难调试的。

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

    综上,setTimeout其实想用好还是很困难的, 他更多的出现是在框架和类库中,例如一些实现Promis的框架,就用上了setTimeout去实现异步。
    所以假如你想去阅读一些源码,想去造一些轮子,setTimeout还是必不可少的工具。

  • 相关阅读:
    go函数
    Linux 查看磁盘容量、查找大文件、查找大目录
    五分钟理解一致性哈希算法(consistent hashing)
    使用Java实现三个线程交替打印0-74
    Python实现IOC控制反转
    Wannafly挑战赛5 A珂朵莉与宇宙 前缀和+枚举平方数
    Yandex Big Data Essentials Week1 Scaling Distributed File System
    Yandex Big Data Essentials Week1 Unix Command Line Interface Processes managing
    Yandex Big Data Essentials Week1 Unix Command Line Interface File Content exploration
    Yandex Big Data Essentials Week1 Unix Command Line Interface File System exploration
  • 原文地址:https://www.cnblogs.com/leolovexx/p/6729178.html
Copyright © 2020-2023  润新知