JS之定时器&异步&回调&函数节流

定时器

  • setTimeout()

    • 用于指定某个任务在多少毫秒的延迟后执行
    • 接收两个参数
      • 字符串代码或函数名或匿名函数
      • 多少毫秒后执行
    • 返回定时器ID,可用clearTimeout(定时器ID)来取消定时器
    console.log(1);
    setTimeout('console.log(2)',1000);
    console.log(3);
    //1
    //3
    //2
    
    function sayHello(){
      console.log("hello")
    }
    console.log(1)
    setTimeout(sayHello,1000)
    console.log(3)
    //1
    //3
    //hello
    
    console.log(1)
    setTimeout(function(){
      console.log("hello")
    },1000)
    console.log(3)
    //1
    //3
    //hello
    
  • setInterval()

    • 用于指定某个任务每隔多少毫秒就执行一次
    • clearInterval()方法用于取消对应的定时器
    • 除上述描述外,其他用法与setTimeout相同

异步

阅读下面的示例代码后,你可能会有如下疑问

function sayHello(){
  console.log("hello")
}
console.log(1)
setTimeout(sayHello,1000)
console.log(3)
//1
//3
//hello

为什么不是先输出1,然后等待1000毫秒,输出hello,然后再输出3?

  • JS本身是单线程的

  • 任务队列机制
    此处引用阮一峰博客中的内容

    所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

  • Event Loop

    主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。为了更好地理解Event Loop,请看下图(转引自Philip Roberts的演讲《Help, I'm stuck in an event-loop》)。

    JS之定时器&异步&回调&函数节流_第1张图片
    image

    回调

    function doSomething(){
      setTimeout(function(){
        console.log(1)
      },2000)
    }
    function doSomething2(){
      console.log(2)
    }
    doSomething()s
    doSomething2()
    

    如果我想实现先输出1,后输出2,应该怎么写呢?
    我们可以通过回调来实现

    function doSomething(callback){
      setTimeout(function(){
        console.log(1)
        callback();
      },2000)
    }
    function doSomething2(){
      console.log(2)
    }
    doSomething(doSomething2)
    

函数节流

假设现在有这么一个场景,当我滚动结束的时候,做一些事情。但是我如何判断当前的滚动是最后一次呢?

var timer
function hiFrequency() {
  if (timer) {
    clearTimeout(timer)
  }
  timer = setTimeout(function () {
    console.log('do something')
  }, 300)
}
hiFrequency()
hiFrequency()
hiFrequency()

如果我再次滚动,调用函数,取消上一次的定时器,重新设置一个定时器。

这样无论函数执行多少次,最终定时器中的任务之后被执行一次。

上述代码改进:

function throttle(fn, delay) {
  var timer = null
  return function () {
    clearTimeout(timer)
    timer = setTimeout(function () {
      fn(arguments)
    }, delay)
  }
}

function fn() {
  console.log('hello ')
}

var fn2 = throttle(fn, 1000)
fn2()
fn2()
fn2()

代码引用自http://book.jirengu.com/fe/%E5%89%8D%E7%AB%AF%E5%9F%BA%E7%A1%80/Javascript/%E5%AE%9A%E6%97%B6%E5%99%A8.html

你可能感兴趣的:(JS之定时器&异步&回调&函数节流)