前端工程師們都聽(tīng)過(guò)看起來(lái)很高級(jí)的詞,節(jié)流和防抖玷过,其實(shí)節(jié)流就是throttle筑煮,防抖就是debounce真仲,其實(shí)這個(gè)也屬于前端性能優(yōu)化的一部分。
在做遠(yuǎn)程搜索時(shí)虑凛,如果每輸入1個(gè)字就調(diào)用1次接口,就會(huì)頻繁查詢數(shù)據(jù)庫(kù)延柠,假設(shè)我們的查詢是"一二三四五"锣披,不考慮用戶輸入錯(cuò)誤的情況,至少會(huì)請(qǐng)求5次榜跌。
- 有沒(méi)有一種方法盅粪,可以隔個(gè)幾百毫秒再去查詢呢?
- 有沒(méi)有更加高級(jí)的做法础浮,用戶輸入完成后奠骄,停頓了幾百毫秒再去查詢呢含鳞?
有沒(méi)有一種方法,可以隔個(gè)幾百毫秒再去查詢呢鸭廷?
有熔吗,可以為函數(shù)設(shè)置一個(gè)setTimeout函數(shù),相當(dāng)于定時(shí)調(diào)用接口讼载,這種方法是低效的中跌,也是非常愚蠢的,需要控制開(kāi)關(guān)定時(shí)器吱型,一旦搜索功能多了陨仅,就更蠢了。
有沒(méi)有更加高級(jí)的做法触徐,用戶輸入完成后撞鹉,停頓了幾百毫秒再去查詢呢?
有享郊,debounce就是做這個(gè)事情的孝鹊,lodash從0.1.0就支持了這個(gè)方法。
css-tricks的lodash debounce demo
<input type="text" class="autocomplete">
// 被debounce的函數(shù)苔咪,http請(qǐng)求柳骄,事件處理函數(shù)等等
function make_ajax_request(){
// 這是一個(gè)調(diào)用后端api的方法
}
// 監(jiān)聽(tīng)事件并且調(diào)用lodash的debounce方法
$('.autocomplete').on('keydown',
_.debounce(make_ajax_request, 1300));
});
vue項(xiàng)目中的lodash debounce demo
<template>
<input @input="debounceHandleInput"/>
</template>
<script>
import _ from 'lodash';
export default {
name: 'debounce',
data() {
return {
starTime: 0,
endTime: 0,
delay: 1000,
};
},
computed: {
debounceHandleInput() {
return _.debounce(this.handleInput, this.delay);
},
},
methods: {
handleInput(e) {
console.log(`debounce wait時(shí)間為${this.delay}ms`);
console.log('觸發(fā)了input事件', e.target.value);
this.startTime = new Date().getTime();
this.remoteMethod();
},
remoteMethod() {
setTimeout(() => {
const result = `后端請(qǐng)求已完成舔清!`;
this.endTime = new Date().getTime();
const costTime = this.endTime - this.startTime;
console.log(result);
console.log(`耗時(shí)${costTime}毫秒`);
}, 2000);
},
},
};
</script>
打印結(jié)果:
debounce wait時(shí)間為1000ms
觸發(fā)了input事件 13131
后端請(qǐng)求已完成曲初!
耗時(shí)2000毫秒
在1000ms時(shí)間范圍內(nèi)觸發(fā),僅僅調(diào)用一次remoteMethod,也就是僅僅調(diào)用一次后端接口目锭,達(dá)到我們的預(yù)期效果纷捞。
debounce適用場(chǎng)景
- Debouncing a input event handler (this example explain this use case)
- Debouncing a resize event handler
- Debouncing a save function in an autosave feature
在做滾動(dòng)加載時(shí),如果用戶滾動(dòng)的幅度過(guò)大奖唯,會(huì)導(dǎo)致加載的內(nèi)容過(guò)多丰捷,相當(dāng)于水的流量沒(méi)有控制,一瞬間大量的水量迸發(fā)而出病往,從而所看到的延后好幾個(gè)與預(yù)期的下一個(gè)不符的情況
- 當(dāng)水流超過(guò)閥值時(shí)停巷,最多釋放出閥值量的水;水流小于閥值時(shí)蕾各,一切正常庆揪。有沒(méi)有一種辦法去控制水流的大腥铝颉?
有仔掸,throttle就是做這個(gè)事情的起暮,lodash從0.1.0也支持了這個(gè)方法。
具體demo就不寫了筒捺,因?yàn)?strong>throttle常用于連續(xù)事件的事件處理函數(shù)纸厉。
可以參考 https://css-tricks.com/the-difference-between-throttling-and-debouncing/ 文章最后的demo颗品,其中的throttle在scroll上的運(yùn)用,就是throttle的正確打開(kāi)方式则吟。
throttle適用場(chǎng)景
- Throttling a scroll event in infinite scroll(demo case)
- Throttling a mousemove/touchmove event handler in canvas
debounce和throttle的對(duì)比
地址:http://demo.nimius.net/debounce_throttle/
圖片:
通過(guò)在canvas上連續(xù)觸發(fā)mousemove事件我們發(fā)現(xiàn):
- debounce只有當(dāng)連續(xù)事件停止后的一小段時(shí)間后再觸發(fā)一次氓仲,連續(xù)事件結(jié)束后可能只觸發(fā)一次
- throttle會(huì)在連續(xù)事件的過(guò)程中敬扛,每隔一段時(shí)間至少觸發(fā)一次,連續(xù)事件結(jié)束后觸發(fā)不止一次
努力成為一個(gè)不掉隊(duì)的前端工程師舔哪!
期待和大家交流,共同進(jìn)步捉蚤,歡迎大家加入我創(chuàng)建的與前端開(kāi)發(fā)密切相關(guān)的技術(shù)討論小組:
- SegmentFault技術(shù)圈:ES新規(guī)范語(yǔ)法糖
- SegmentFault專欄:趁你還年輕缆巧,做個(gè)優(yōu)秀的前端工程師
- 知乎專欄:趁你還年輕,做個(gè)優(yōu)秀的前端工程師
- Github博客: 趁你還年輕233的個(gè)人博客
- 前端開(kāi)發(fā)QQ群:660634678
微信公眾號(hào): 人獸鬼 / excellent_developers
努力成為優(yōu)秀前端工程師题暖!