《JavaScript高级程序设计》读书笔记22.3高级定时器

  • 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)
  • 主线程外,还有一个“任务队列”(task queue)。只要异步任务有了结果,就在“任务队列”中放置一个事件,同时执行相应代码。
  • 定时器对“任务队列”的工作方式是,当特定时间过去后将代码插入。
  • 指定的时间间隔表示何时将定时器的代码添加到队列中,而不是何时实际执行代码。

1. 重复的定时器

  • 当使用setIntervel()时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到“任务队列”。
  • 有两个问题:
    1. 某些间隔会被跳过
    2. 多个定时器的代码执行之间的间隔可能会比预期的小
      clipboard.png
      理解这幅图关键点在于:605ms处,第一个定时器代码仍在运行,同时队列中已经有了一个定时器代码实例,则605ms处被跳过。在600ms多一点处,直接运行405ms添加的代码
  • 解决办法: 链式调用setTimeout()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    setTimeout(function(){
    //处理中
    setTimeout(arguments.callee,intervel)
    },intervel)

    //使用例子
    setTimeout(function(){
    var div=document.getElementById("myDiv");
    var left=parseInt(div.style.left)+5;
    div.style.left=left+"px";

    if(left<200){
    setTimeout(arguments.callee,50);
    }

    },50)

2. Yielding Processes

  • JavaScript被严格限制了内存大小和处理器时间

  • 其中一个限制是长时间运行脚本,即代码运行超过特定的时间或者特定语句数量就不让它继续执行。

  • 两个原因:

    1. 过长的、过深嵌套的函数调用
    2. 进行大量处理的循环
  • 某个循环占用时间长、不需要同步完成、不需要按顺序完成,则可实行数组分块

  • 基本思路: 为要处理的项目创建一个队列,然后使用定时器取出下一个要处理的项目进行处理,接着再设置另一个定时器。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function chunk(array,process[,context]){
    setTimeout(function(){
    var item=array.shift();
    process.call(context,item);

    if(array.length>0){
    setTimeout(arguments.callee,100);
    }
    },100);
    }
  • 克隆数组方法: array.concat();

3. 函数节流

  • 函数节流:阻止某些操作高频率执行。
  • 基本思路:某些代码不可以在没有间断的情况下连续重复执行。
    1
    2
    3
    4
    5
    6
    function throttle(method[,context]){
    clearTimeout(method.tId);
    method.tId=setTimeout(function(){
    method.call(context);
    },100);
    }
liborn wechat
欢迎您扫一扫上面的微信二维码,订阅我的公众号!