对于浏览器的缩放,滚动条的滚动都可能涉及到防抖
实现一个防抖函数需要注意的点:
- 防抖函数是否支持立即执行
- 防抖函数是否支持取消
- 防抖函数是否可以拿到返回值
非防抖
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#container {
width: 100%;
height: 200px;
background: #ccc;
text-align: center;
line-height: 200px;
}
</style>
</head>
<body>
<div id="container">
1
</div>
<script type="text/javascript">
let count = 1
let box = document.getElementById('container')
// function debounce(fn, wait=500) {
// let timer;
// return function(...args) {
// if(timer) {
// clearTimeout(timer)
// }
// timer = setTimeout(()=> {
// fn.apply(this,args)
// }, wait)
// }
// }
function updateCount () {
box.innerHTML=count++
}
// let actived = debounce(updateCount)
box.addEventListener('mousemove', updateCount, true);
</script>
</body>
</html>
防抖函数debouce实现:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#container {
width: 100%;
height: 200px;
background: #ccc;
text-align: center;
line-height: 200px;
}
</style>
</head>
<body>
<div id="container">
1
</div>
<script type="text/javascript">
let count = 1
let box = document.getElementById('container')
function debounce(fn, wait=500) {
let timer;
return function(...args) {
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(()=> {
fn.apply(this,args)
}, wait)
}
}
function updateCount () {
box.innerHTML=count++
}
let actived = debounce(updateCount)
box.addEventListener('mousemove', actived, true);
</script>
</body>
</html>
防抖函数也要能够立即执行
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#container {
width: 100%;
height: 200px;
background: #ccc;
text-align: center;
line-height: 200px;
}
</style>
</head>
<body>
<div id="container">
1
</div>
<script type="text/javascript">
let count = 1
let box = document.getElementById('container')
function debounce(fn, wait=500, immediate=true) {
let timer, rs;
return function(...args) {
if(timer) {
clearTimeout(timer)
}
if(immediate) {
if(!timer) {
rs = fn.apply(this,args)
}
//这里联系setTimeout异步问题
timer = setTimeout(()=> {
timer = null
},wait)
}else {
timer = setTimeout(()=> {
rs = fn.apply(this,args)
}, wait)
}
return rs
}
}
function updateCount () {
box.innerHTML=count++
}
let actived = debounce(updateCount)
box.addEventListener('mousemove', actived, true);
</script>
</body>
</html>
防抖函数支持取消功能
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#container {
width: 100%;
height: 200px;
background: #ccc;
text-align: center;
line-height: 200px;
}
</style>
</head>
<body>
<div id="container">
1
</div>
<button id="cancel">取消</button>
<script type="text/javascript">
let count = 1
let box = document.getElementById('container')
let cancelBtn = document.getElementById('cancel')
function debounce(fn, wait=2000, immediate=false) {
let timer, rs;
let debounced = function(...args) {
if(timer) {
clearTimeout(timer)
}
if(immediate) {
if(!timer) {
rs = fn.apply(this,args)
}
//这里联系setTimeout异步问题
timer = setTimeout(()=> {
timer = null
},wait)
}else {
timer = setTimeout(()=> {
rs = fn.apply(this,args)
}, wait)
}
return rs
}
debounced.cancel = function () {
clearTimeout(timer)
}
return debounced;
}
function updateCount () {
box.innerHTML=count++
}
let active = debounce(updateCount)
box.addEventListener('mousemove', active, true);
cancelBtn.addEventListener('click', active.cancel, true);
</script>
</body>
</html>
如果我们的函数执行的过程中存在异常,如何进行处理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#container {
width: 100%;
height: 200px;
background: #ccc;
text-align: center;
line-height: 200px;
}
</style>
</head>
<body>
<div id="container">
1
</div>
<button id="cancel">取消</button>
<script type="text/javascript">
let count = 1
let box = document.getElementById('container')
let cancelBtn = document.getElementById('cancel')
function debounce(fn, wait=500, immediate=true) {
let timer, rs;
let debounced = function(...args) {
if(timer) {
clearTimeout(timer)
}
if(immediate) {
let callnow = !timer;
//这里联系setTimeout异步问题
timer = setTimeout(()=> {
timer = null
},wait)
if(callnow) {
rs = fn.apply(this,args)
}
}else {
timer = setTimeout(()=> {
rs = fn.apply(this,args)
}, wait)
}
return rs
}
debounced.cancel = function () {
clearTimeout(timer)
}
return debounced;
}
function updateCount () {
box.innerHTML=count++
throw Error('aa')
}
let active = debounce(updateCount)
box.addEventListener('mousemove', active, true);
cancelBtn.addEventListener('click', active.cancel, true);
</script>
</body>
</html>