优化网络请求性能-节流(throttle)
什么是节流
函数节流就是预定一个函数只有在大于等于执行周期的时候才会执行,周期内不执行。好像水滴攒到一定重量才会落下。
为什么要节流
在前端开发中有一部分用户行为会频繁的触发事件执行,而对于DOM操作,资源加载等耗费性能的处理,很可能导致页面卡顿,甚至浏览器的崩溃。函数节流(throttle)和函数防抖(debounce)就是为了解决类似需求应用而生的。
节流的应用场景
- 窗口调整(resize)
- 页面滚动(scroll)
- 抢购疯狂点击(mousedown)
节流代码实现
这里以点击按钮,上面的内容点击一次加1来做一个节流。 未做节流之前,点的越快,增加的越快。那么如果直接写一个for循环点击按钮那么1s内点1000次,会给页面和服务器消耗大量的性能甚至崩溃。所以需要写一个节流。
实现思路 : 点击按钮 1000ms内不断点击多少次都只加一次,过了1000ms后在点击的话在增加一次。
eg1:未优化的代码 (点的越快增加的越快)
<div id="demo">0</div>
<button id="btn">click</button>
var oDiv = document.getElementById('demo');
var oBtn = document.getElementById('btn');
oBtn.onclick = function () {
oDiv.innerText = parseInt(oDiv.innerText) + 1;
}
eg2:节流函数封装
<div id="demo">0</div>
<button id="btn">click</button>
var oDiv = document.getElementById('demo');
var oBtn = document.getElementById('btn');
function buy () {
oDiv.innerText = parseInt(oDiv.innerText) + 1;
}
// 节流函数
function throttle (handler,wait) {
// handler : 处理函数 wait: 等待时间
var lastTime = 0;
return function () { // return函数的原因,onclick绑定的是函数体不是立即执行
var nowTime = new Date().getTime();
if(nowTime - lastTime > wait) {
handler();
lastTime = nowTime;
}
}
}
oBtn.onclick = throttle(buy,1000); //点击俩次点击时间超过1000ms的时候会执行buy
eg3 : eg2中handler的事件对象没有,this指向window。想要改变this,和加上事件对象
<div id="demo">0</div>
<button id="btn">click</button>
var oDiv = document.getElementById('demo');
var oBtn = document.getElementById('btn');
function buy () {
oDiv.innerText = parseInt(oDiv.innerText) + 1;
}
// 节流函数
function throttle (handler,wait) {
// handler : 处理函数 wait: 等待时间
var lastTime = 0;
return function (e) { // return函数的原因,onclick绑定的是函数体不是立即执行
var nowTime = new Date().getTime();
if(nowTime - lastTime > wait) {
handler.apply(this,arguments); //this - > oBtn arguments--e 系统传入的事件对象
lastTime = nowTime;
}
}
}
oBtn.onclick = throttle(buy,1000); //点击俩次点击时间超过1000ms的时候会执行buy
优化页面请求性能–防抖(debounce)
什么是防抖
函数防抖就是函数需要频繁触发时,只有足够空闲的时间才会执行一次。好像公交车司机等人都上车之后才出站一样。
应用场景
- 实时搜索(keyup)
如百度中搜索nba,如果不做防抖时候,在input中输入n时,向后端发生一次请求,输b时又发一次,输a时,又发一次。 其实用户真实就是想输入nba,那么其中前俩次输入(nb)时发生请求就是无用的,浪费性能。为了优化这个性能,所以需要做防抖操作,只有当输入到最后a之后,隔一段时间不触发input事件了,那么在发送请求。 就好像有人一直上车时,司机不开车,当最后一个人上车了,司机看看有没有人上车了没人上了停几秒,在开车。 - 拖拽(mousemove)
防抖实现
eg1:
<input type="text" id="inp">
var timer = null;
var inp = document.getElementById('inp');
function ajax () {
console.log(this.value)
}
inp.oninput = function () {
var self = this;
clearTimeout(timer); //如果一直触发函数,那么触发一次清楚到上一次的定时器
timer = setTimeout(function () {
ajax.apply(self);
} ,1000)
}
eg2:防抖功能抽象出来
<input type="text" id="inp">
var inp = document.getElementById('inp');
function ajax (e) {
console.log(this.value , e);
}
function debounce (handler,delay) {
var timer = null;
return function (e) {
var self = this;
var arg = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
ajax.apply(self,arg);
},delay)
}
}
inp.oninput = debounce(ajax,1000); //最后一次触发事件延迟1000ms执行ajax函数