• 定时器


    setTimeout,setInterval并不是多线程,只是浏览器提供的一个定时的事件触发器,让js代码在浏览器中延时执行。

    let timeoutID = window.setTimeout(func[, delay, param1, param2, ...]);  //param1/param2为func执行时的参数,ie9以下不支持
    setTimeout:通知浏览器,在delay毫秒之后,将定时器任务func加入事件队列,只加一次。

    setInerval:每延时delay毫秒之后,浏览器尝试将定时器任务加入事件队列。如果事件队列中已经存在该timer未执行的消息,则该回调会被丢弃,不再添加。否则,会出现多个回调同时在队列等待执行的情况。

    定时器只负责到时往队列中加入消息,具体执行时间要看队列中的消息排队情况。所以setTimeout(fun, 0)并不意味着立即执行。

    事件消息无论何时添加,总是优先于定时器消息执行,因为各种task的优先级不同。

    $('#ele1').on('click', function () {
        var oldTime = new Date().getTime();
        while (new Date().getTime() - oldTime < 2000) { }
        console.log('clickEvent1');
    });
    $('#ele2').on('click', function () {
        var oldTime = new Date().getTime();
        while (new Date().getTime() - oldTime < 2000) { }
        console.log('clickEvent2');
    });
    var timer = setTimeout(function () {
        console.log('timerEvent');
    }, 0)
    $('#ele1').click();
    $('#ele2').click();
    $('#ele1').click();
    //输出clickEvent1,clickEvent2,clickEvent1,timerEvent

    如果执行时间长,setInterval会导致两次回调间没有delay,这时可以采用链式调用setTimeout来取代setInterval。

    function timer(fn,delay){
        var s=setTimeout(function(){
              fn();
              timer(fn,delay);    //回调执行完重新触发定时器,避免了连续的队列延迟产生的叠加
          },delay) 
    }     

    var timer=setTimeout(function () {
        //业务逻辑...
        timer=setTimeout(arguments.callee, interval);
    }, interval)
    //为了在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔,也保证了在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行。

    另外:建议使用requestAnimationFrame(RAF)或者直接采用CSS来写页面动画,不要使用定时器。requestAnimationFrame比起setTimeout、setInterval的优势主要有两点:

    1.requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

    2.在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

    setTimeout(fn,0)的妙用:将同步代码转为异步执行。

    <div id="progress"></div>
    <script>
      let i = 0;
      function count() {
        for(let j = 0; j < 1e6; j++) {
          i++;
          // put the current i into the 
          progress.innerHTML = i;
        }
      }
      count();
    </script>

    优化如下:

    <div id="progress"></div>
    <script>
      let i = 0;
      function count() {
        // do a piece of the heavy job (*)
        do {
          i++;
          progress.innerHTML = i;
        } while (i % 1e3 != 0);
        if (i < 1e9) {
          setTimeout(count, 0);//pause between heavy job give the broswer chance to do ui rendering
        }
      }
      count();
    </script>

    setTimeout(IIFE,delay):如果第一个参数是立即执行函数或函数调用,则会在当前函数执行栈立即执行,不会延迟执行。可以再嵌套一层匿名函数让其延迟。
    SetTimeout's first argument expects a reference to function. And IIFE runs the function, the result of its execution is passed to setTimeout. If the function returns nothing/undefined,then nothing is scheduled.

    setTimeout(function(){
        console.log(1);        //IIFE函数,会在当前函数执行栈之上立即执行
        return "alert('3')";    //IIFE函数的返回值作为定时器的函数体
    }(),1000);
    console.log(2)        //script为macotask,继续执行当前任务
    以上皆为个人理解,如有错误之处,欢迎留言指正。
  • 相关阅读:
    链家网各城市二手房价格
    mitmproxy 配置
    Python操作APP -- Appium-Python-Client
    Appium连接模拟器
    adb server version (xx) doesn't match this client (xx); killing...
    Appnium 环境搭建
    KeyError: 'xxx does not support field: _id'
    Python执行JS -- PyExecJS库
    Python -- CSV文件读写
    Git的基本使用 -- 分支管理
  • 原文地址:https://www.cnblogs.com/kevin2chen/p/6415750.html
Copyright © 2020-2023  润新知