• setTimeout,setInterval的使用小结


    setTimeout

    众所周知setTimeout(fn,time)是等待一段时间后,执行函数fn。
    在这个等待是异步的,也就是他不会站着茅坑,当前JS队列中的其他任务会按序执行
    但这里有个问题就是time毫秒过后的fn执行问题。是立即执行?不一定。
    这就像是一个买票的队伍,有正在买票的,有排在后面等待买票的。而setTimeout就相当于刚排到fn买票的时候他突然发现钱包一时翻不出来。
    所以他就让后面的人先买。过了time时间找到钱包后,如果现在没人买票的话,他可以立即买票。否则他就只能去排队了(当所有队列中的内容执行结束后才执行)。

    <input type="text" id="io" />
    <div id="test" style="200px;height:400px;overflow:scroll;"></div>
    <script>
    //这个函数的执行时间在IE下肯定是大于100ms的
    function lost() {
        var test = document.getElementById("test");
        var t1 = new Date();
        var html = [];
        for (var i = 0; i < 10000; i++) {
            html.push('<span>look at here</span>');
        }
        test.innerHTML = html.join("");
        var t2 = new Date();
        //return (t2 - t1) / 1000;纠正
        return t2 - t1;
    }
    var io = document.getElementById("io"); io.value += "A"; setTimeout(function() { io.value += "B"; }, 100); lost(); io.value += "C"; lost(); io.value += "D"; </script>

    最后io的value为ACDB,也证明了不是100ms后立即执行,而是排到了队伍后面。

    也有人见过setTimeout(fn,0);如果上面的内容理解了的话,这个也就不难了:如果没有队伍则立即执行,否则就排队去。


    setInterval

    setInterval(fn,time)就是一个重复的定时器。
    每隔time时间,将fn推入队列(如果进程空闲则立刻执行),不管是否有fn正在执行或等待队列。
    但是,如果当前队列中有正在等待的fn,则本次不会向队列中添加fn。如下

    <input type="text" id="io" />
    <input type="button" id="insert" value="INSERT" />
    <input type="button" id="get" value="GET" />
    <div id="test" style="200px;height:400px;overflow:scroll;"></div>
    <script>
        var io = document.getElementById("io");
        var i = setInterval(function() {
            io.value += "B";
        }, 10);
        
        lost();
        lost();
        setTimeout(function() {
            clearInterval(i);
        }, 10);
        
        //IE下执行时间肯定会是10的好多倍的
        function lost() {
            var test = document.getElementById("test");
            var t1 = new Date();
            var html = [];
            for (var i = 0; i < 10000; i++) {
                html.push('<span>look at here</span>');
            }
            test.innerHTML = html.join("");
            var t2 = new Date();
            io.value += "C";
        }
    </script>

    结果是CCB
    执行lost函数的时间是定时器的很多倍。但在这么长的时间里,定时器只向队列中推入fn一次。
    这个原因也导致了以下两种不理想情况的出现。

    ①fn执行时间小于time的时候,经常会间隔时间不一致。

    ②fn执行时间大于time时,则造成没有了间隔时间(实际当中会有那么一点点的间隔)

    因为这些问题,setInterval就失去了定时器的意义。

    所以我们都用循环调用setTimeout来代替setInterval。原理如下

    setInterval(fn,time)
    //↓↓↓↓↓↓↓↓↓↓↓↓
    setTimeout(function(){
        fn();
        setTimeout(arguments.callee,time);
    },time);

    这样就可以让每个fn之间都会至少保持time的间隔。 

    注:setTimeout和setInterval的函数环境总是Window。


  • 相关阅读:
    深入理解jvm分享培训pdf(转载) 老李
    innobackupex自动备份脚本(增量备份,自动压缩)
    多线程调用生成主键流水号存储过程产生主键冲突问题解决方案
    mysql 5.7新数据库sys解析(一)
    根据日期累加金额的mysql
    mysql字符串分割函数(行转列)
    使用innobackupex备份mysql数据库
    css学习inlineblock详解及dispaly:inline inlineblock block 三者区别精要概括
    html良好结构之豆瓣风格
    HTML5学习笔记html5与传统html区别
  • 原文地址:https://www.cnblogs.com/TiestoRay/p/2779160.html
Copyright © 2020-2023  润新知