zoukankan      html  css  js  c++  java
  • setTimeout详解

    https://www.cnblogs.com/wzndkj/p/7069331.html

    一、setTimeout基础

    setTimeout(func|code,delay);
    第一个参数表示将要推迟的函数名或者一段代码,第二个参数表示推迟执行的毫秒数
     
    复制代码
    eg:
    console.log(1);
    setTimeout('console.log(2)',1000);
    console.log(3);
    
    answer:
    1
    3
    2
    复制代码
     
    *:推迟的代码必须以字符串的形式,因为引擎内部使用eval()函数,将字符串转为代码。
    *:如果推迟执行的是函数,则可以直接将函数名,放入setTimeout()
     
    复制代码
    eg:
    function func(){
      console.log(2);
    }
    setTimeout(func,5000);
    //或者
    setTimeout(function(){
      console.log(2);
    },1000)
    复制代码

    *:如果写成setTimeout(func(),5000);func会立即执行

    二、setTimeout支持更多的参数
    复制代码
    eg:
    setTimeout(function(a,b){
      console.log(a+b);
    },1000,4,5)
    
    //4,5 9
    //'str' '2' str2
    复制代码
     
    *:从第三个参数开始,依次用来表示第一个参数(回调函数)传入的参数
    *:一些古老的浏览器是不支持,可以用bind或apply方法来解决
     
    eg:
    setTimeout(function(a,b){
      console.log(a+b);
    }.bind(this,4,5),1000)
     
    *:第一个参数表示将原函数的this绑定全局作用域,第二个参数开始是要传入原函数的参数
    *:当调用绑定函数时,绑定函数会以创建它时传入bind()方法的第一个参数作为 this
     
    三、setTimeout()中回调函数中的this
    复制代码
    eg:
    var a=1;
    var obj={
      a:2,
      b:function(){
        setTimeout(function(){
          console.log(this.a);
        },2000);
      }
    };
    obj.b();
    复制代码
     
    上面代码输出的是1,而不是2,表示o.b的this所指向的已经不是o,而是全局环境了
    可以用bind()来改变这个情况:
     
    复制代码
    var a=1;
    var obj={
        a:2,
        b:function(){
            setTimeout(function(){
                console.log(this.a);
            }.bind(this),2000);//注意这行
        }
    };
    obj.b();        
    复制代码
    四、setTimeout()执行回调间隔时间长度
     
    var startTime = new Date();
    setTimeout(function () {
        console.log(new Date() - startTime);
    }, 100);
     
    //100+ 取决于后面同步执行的JS需要占用多少时间
     
     
    五、setTimeout(func,0)
    复制代码
    eg:func1和func2谁会先执行?
    
    function func1(){
        console.log(1);
    }
    function func2(){
        console.log(2);
    }
    setTimeout(function () {
        func1();
    }, 0)
    func2();
    复制代码
    setTimeout(function(){
        func1()
    },0)
    setTimeout(function(){
        func1();
    })

    有什么差别?

    0秒延迟,此回调将会放到一个能立即执行的时段进行触发。javascript代码大体上是自顶向下的,但中间穿插着有关DOM渲染,事件回应等异步代码,他们将组成一个队列,零秒延迟将会实现插队操作。
    不写第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。
     
     
     
    六、setTimeout和单线程
    首先需要注意javascript是单线程的,特点就是容易出现阻塞。如果一段程序处理时间很长,很容易导致整个页面hold住。什么交互都处理不了怎么办?

    setTimeout一个很关键的用法就是分片,如果一段程序过大,我们可以拆分成若干细小的块。
    例如上面的情况,我们将那一段复杂的逻辑拆分处理,分片塞入队列。这样即使在复杂程序没有处理完时,
    我们操作页面,也是能得到即使响应的。其实就是将交互插入到了复杂程序中执行。

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

    有个函数库Concurrent.Thread.js 就是实现js的多线程的
    复制代码
    eg:Concurrent.Thread.create(function(){
        for(var i=0; i<100000000; i++){
            console.log(i);
        }
    })
    
    $('#test').click(function(){
        alert(1);
    });
    复制代码
    虽然有个巨大的循环,但是这时不妨碍你去触发alert();
    当我们需要渲染一个很复杂的DOM时,例如table组件,复杂的构图等等,
    假如整个过程需要3s,我们是等待完全处理完成在呈现,还是使用一个setTimeout分片,
    将内容一片一片的断续呈现。
    其实setTimeout给了我们很多优化交互的空间。
     
     
    七、如何使用
    setTimeout这么厉害,那么我们是需要在在项目中大量使用吗?
    我这边的观点是非常不建议,在我们业务中,基本上是禁止在业务逻辑中使用setTimeout的

    例如,当一个实例还没有初始化的前,我们就使用这个实例,错误的解决办法是使用实例时加个setTimeout,确保实例先初始化。
    为什么错误?这里其实就是使用hack的手段
    第一是埋下了坑,打乱模块的生命周期
    第二是出现问题时,setTimeout其实是很难调试的。

    综上,setTimeout其实想用好还是很困难的,时间的不确定性,排队运算混乱, 他更多的出现是在框架和类库中,例如一些实现Promis的框架,就用上了setTimeout去实现异步。
  • 相关阅读:
    C++中substr函数的用法
    最小生成树-克鲁斯卡尔模板
    最小生成树-prim算法模板
    1064. 朋友数(20)
    1076. Wifi密码 (15)【模拟】
    二分搜索与二分答案
    HDU 1969 Pie【二分】
    1047. 编程团体赛(20)
    1057. 数零壹(20)
    L2-3. 悄悄关注【STL+结构体排序】
  • 原文地址:https://www.cnblogs.com/beimingbingpo/p/8532023.html
Copyright © 2011-2022 走看看