前端面试题整理(一)--防抖和节流、event loop

一、防抖和节流原理及实现
二、event loop

一、防抖和节流原理及实现

1、防抖

当一个事件被频繁触发时,禁止执行,直到触发频率降低到某一程度时,才会执行
原理:
当一个事件被频繁触发时,禁止执行,直到停止触发后,间隔指定时间后再执行
在vue中使用防抖函数的步骤:

  data() {
    return {
      timeout: null,
      //触发次数
      num:0,
      //执行次数
      countNum:0
    }
},
methods: {
    debounce(fn, time) {
      let that = this
      return function() {
        clearTimeout(that.timeout)
        that.timeout = setTimeout(() => {
          fn()
          // fn中的this指向debounce中return的这个函数的this(即调用这个debounce函数的函数)
          // fn.apply(this)
        }, time)
      }
    },
    count() {
      console.log('执行次数count', this.countNum++)
    },
    test() {
      console.log('触发次数', this.num++)
      this.debounce(this.count, 5000)()
    }
}

执行结果
image.png

可以看到触发了多次,但是只执行了一次,达到了我们预先想要的效果

2、节流

原理:
当一个事件被频繁触发时,保持规定的时间间隔,每隔一段时间执行一次,不受触发频次的影响

data() {
    return {
      timeout: null,
      //触发次数
      num:0,
      //执行次数
      countNum:0
      //节流标志
      flag: true
    }
},
methods: {
    throttle(fn, time) {
      let that = this
      return function() {
        // 如果是false,则结束,如果是true,则继续
        if (!that.flag) { return false }
        that.flag = false
        setTimeout(() => {
          fn()
          that.flag = true
        }, time)
      }
    },
    count() {
      console.log('执行次数count', this.countNum++)
    },
    test() {
      console.log('触发次数', this.num++)
      this.throttle(this.count, 500)()
    }
}

执行结果
image.png

如图所示,不管我们触发多少次,fn的执行都是以一定的时间频率执行,实现了我们预期的效果

二、event loop

宏任务(MacroTask/Task)

  • script中全部代码
  • DOM操作(UI rendering)
  • 用户交互操作
  • 所有的网路请求(I/O)
  • 定时器相关的 setTimeout、setInterval 等
  • nodejs方法setImmediate

微任务(MircoTask)

  • Promise中的then、catch、finally
  • postMessage

1、浏览器的Event loop

每一次/层循环,都是首先从宏任务开始,微任务结束;
将宏任务排优先级后,就一层一层循环
任务队列,先进先出

举个栗子
image.png

分析:

1、先执行第一层宏任务,输出1,4
2、再执行微任务,输出3
3、至此第一层循环结束,接下来进行第二层循环
4、执行第二层红任务setTimeout输出2
5、所以最终输出结果为【1,4,3,2】

举个复杂的栗子
image.png

分析过程同上

最后输出结果为【start,promise inner2,promise then2,setTimeout,promise inner1,promise then1】
image.png

async和await
async 是Promise的语法糖

async function test() {
    return 1   // async的函数会在这里帮我们隐式使用Promise.resolve(1)
}
// 等价于下面的代码
function test() {
   return new Promise(function(resolve, reject) {
       resolve(1)
   })
}

遇到await时,代码从右向左执行,await async2()会先执行async2(),然后向左执行到await,遇到await时,会阻塞函数体中处于他后面的代码,然后执行函数外部的同步代码,然后执行微任务(这一轮循环就完了,然后进入下一轮循环),执行他后面的代码和第二层宏任务

举个栗子
image.png

分析过程同上,输出结果依次为【start,async1 start,promise1,async2 promise,promise2,async1 end,setTimeout】
image.png

1、Node的Event loop

六个阶段

1.timers:执行timer的回调
2.pending callbacks:系统操作的回调(无需关注)
3.idle,pepare:内部使用(无需关注)
4.poll:等待新的I/O事件
5.check:执行setImmediate的回调
6.close callbacks:内部使用(无需关注)
[注意]process.nextTick(),是一个异步的node API,但不属于event loop阶段,他会暂停event loop,先执行nextTick()里的回调,执行完之后再继续event loop

每一个阶段都有一个先进先出的队列,当队列的所有callback执行完或者callback数量超过限制时,event loop会进入下一阶段


image.png

所以执行顺序是I/O-->setImmediate-->timers

举个栗子
image.png

你可能感兴趣的:(前端面试题整理(一)--防抖和节流、event loop)