一、防抖和节流原理及实现
二、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








