forked from YvetteLau/Blog
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
606 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
function simpleDebounce(func, wait) { | ||
let timer = null; | ||
/* 触发时,参数传给了 debounced */ | ||
return function debounced() { | ||
let args = arguments; | ||
if (timer) clearTimeout(timer); | ||
timer = setTimeout(() => { | ||
/* this绑定和参数的传递, | ||
* 注意此处使用的是箭头函数,因此不需要在外层将 this 赋值给某变量 | ||
*/ | ||
func.apply(this, args); | ||
}, wait); | ||
} | ||
} | ||
|
||
|
||
function debounce(func, wait, immediate = true) { | ||
let timer; | ||
// 延迟执行函数 | ||
const later = (context, args) => setTimeout(() => { | ||
timer = null;// 倒计时结束 | ||
if (!immediate) { | ||
func.apply(context, args); | ||
//执行回调 | ||
context = args = null; | ||
} | ||
}, wait); | ||
let debounced = function (...params) { | ||
let context = this; | ||
let args = params; | ||
if (!timer) { | ||
timer = later(context, args); | ||
if (immediate) { | ||
//立即执行 | ||
func.apply(context, args); | ||
} | ||
} else { | ||
clearTimeout(timer); | ||
//函数在每个等待时延的结束被调用 | ||
timer = later(context, args); | ||
} | ||
} | ||
debounced.cancel = function () { | ||
clearTimeout(timer); | ||
timer = null; | ||
}; | ||
return debounced; | ||
}; | ||
|
||
export { simpleDebounce, debounce } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/** 时间戳 */ | ||
function tampThrottle (func, delay) { | ||
var lastTime = 0; | ||
function throttled() { | ||
var context = this; | ||
var args = arguments; | ||
var nowTime = Date.now(); | ||
if(nowTime > lastTime + delay) { | ||
func.apply(context, args); | ||
lastTime = nowTime; | ||
} | ||
} | ||
//防抖函数最终返回的是一个函数 | ||
return throttled; | ||
} | ||
|
||
/** 定时器实现 */ | ||
function timeThrottle(func, wait) { | ||
let timer; | ||
return function throttled() { | ||
let args = arguments; | ||
if (!timer) { | ||
timer = setTimeout(() => { | ||
func.apply(this, args); | ||
clearTimeout(timer); | ||
timer = null; | ||
}, wait); | ||
} | ||
} | ||
} | ||
|
||
function throttle(func, wait, options) { | ||
var timeout, result; | ||
var previous = 0; | ||
if (!options) options = {}; | ||
|
||
var later = function (context, args) { | ||
previous = options.leading === false ? 0 : Date.now() || new Date().getTime(); | ||
timeout = null; | ||
result = func.apply(context, args); | ||
}; | ||
|
||
var throttled = function () { | ||
var now = Date.now() || new Date().getTime(); | ||
if (!previous && options.leading === false) previous = now; | ||
var remaining = wait - (now - previous); | ||
let context = this; | ||
let args = arguments; | ||
if (remaining <= 0 || remaining > wait) { | ||
if (timeout) { | ||
clearTimeout(timeout); | ||
timeout = null; | ||
} | ||
previous = now; | ||
result = func.apply(context, args); | ||
if (!timeout) context = args = null; | ||
} else if (!timeout && options.trailing !== false) { | ||
// 判断是否设置了定时器和 trailing | ||
timeout = setTimeout(() => { later(context, args) }, remaining); | ||
} | ||
return result; | ||
}; | ||
|
||
throttled.cancel = function () { | ||
clearTimeout(timeout); | ||
previous = 0; | ||
timeout = null; | ||
}; | ||
|
||
return throttled; | ||
} | ||
|
||
export { tampThrottle, timeThrottle, throttle } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head lang="zh-CN"> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<title></title> | ||
<style> | ||
.base { | ||
height: 200px; | ||
width: 200px; | ||
background: pink; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
cursor: pointer; | ||
} | ||
|
||
p { | ||
-webkit-user-select: none; | ||
-moz-user-select: none; | ||
-ms-user-select: none; | ||
user-select: none; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<div class="base"> | ||
<p>点击触发事件</p> | ||
</div> | ||
</body> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script> | ||
<script> | ||
window.onload = function () { | ||
function debounce(func, wait, immediate = true) { | ||
let timer; | ||
// 延迟执行函数 | ||
const later = (context, args) => setTimeout(() => { | ||
timer = null;// 倒计时结束 | ||
if (!immediate) { | ||
func.apply(context, args); | ||
//执行回调 | ||
context = args = null; | ||
} | ||
}, wait); | ||
let debounced = function (...params) { | ||
let context = this; | ||
let args = params; | ||
if (!timer) { | ||
timer = later(context, args); | ||
if (immediate) { | ||
//立即执行 | ||
func.apply(context, args); | ||
} | ||
} else { | ||
clearTimeout(timer); | ||
//函数在每个等待时延的结束被调用 | ||
timer = later(context, args); | ||
} | ||
} | ||
debounced.cancel = function () { | ||
clearTimeout(timer); | ||
timer = null; | ||
}; | ||
return debounced; | ||
}; | ||
|
||
|
||
function handleClick(e) { | ||
console.log(this); //this值正确传递 | ||
console.log(e, [...arguments].splice(1)); //参数正确传递 | ||
} | ||
|
||
/* 防抖,immediate = ture 每个等待时延的开始被调用 */ | ||
let handle = debounce(handleClick, 1000, true); | ||
// let handle = _.debounce(handleClick, 1000, { | ||
// leading: true, | ||
// trailing: false | ||
// }); | ||
document.querySelector('.base').onclick = handle; | ||
} | ||
|
||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import { simpleDebounce, debounce } from '../src/debounce'; | ||
import { EventEmitter } from 'events'; | ||
|
||
/** | ||
* 每 300 ms 触发一次 down 事件,共触发 3 次 | ||
* 防抖的间隔时间是 200ms,因此 frequency 被调用了 3次 | ||
*/ | ||
test('simpleDebounce/事件处理函数被调用3次 ', (done) => { | ||
let myEvent = new EventEmitter(); | ||
/** 高频 down 事件处理函数 */ | ||
const frequency = jest.fn(); | ||
/** 间隔时间为 200ms */ | ||
let debounceFrequency = simpleDebounce(frequency, 200); | ||
|
||
myEvent.on('down', () => { | ||
debounceFrequency('hello'); | ||
}); | ||
/** 共触发 3 次 */ | ||
let i = 0; | ||
function delay(callback, interval) { | ||
let timer = setTimeout(() => { | ||
if (i < 3) { | ||
myEvent.emit('down'); | ||
delay(callback, interval); | ||
i++; | ||
} else { | ||
clearTimeout(timer); | ||
callback(); | ||
myEvent.removeAllListeners('down'); | ||
} | ||
}, interval); | ||
} | ||
|
||
/** | ||
* 每 300 ms 触发一次 down 事件,共触发 3 次 | ||
* 防抖的间隔时间是 200ms,因此 frequency 被调用了 3次 | ||
*/ | ||
|
||
delay(() => { | ||
expect(frequency.mock.calls.length).toBe(3); | ||
done(); | ||
}, 300); | ||
|
||
}); | ||
|
||
|
||
/** | ||
* 每 100 ms 触发一次 down 事件 | ||
* 防抖的间隔时间是 200ms,因此 frequency2 被调用了 0 次 | ||
*/ | ||
test('simpleDebounce/ 事件处理函数被调用0次 ', (done) => { | ||
let myEvent = new EventEmitter(); | ||
/** 高频 down 事件处理函数 */ | ||
const frequency2 = jest.fn(); | ||
/** 防抖间隔时间为 200ms */ | ||
let debounceFrequency = simpleDebounce(frequency2, 200); | ||
myEvent.on('down', () => { | ||
debounceFrequency('hello'); | ||
}); | ||
/** 共触发 3 次 */ | ||
let i = 0; | ||
function delay(callback, interval) { | ||
let timer = setTimeout(() => { | ||
if (i < 3) { | ||
myEvent.emit('down'); | ||
delay(callback, interval); | ||
i++; | ||
} else { | ||
clearTimeout(timer); | ||
callback(); | ||
myEvent.removeAllListeners('down'); | ||
} | ||
}, interval); | ||
} | ||
|
||
/** | ||
* 每 100 ms 触发一次 down 事件 | ||
* 防抖的间隔时间是 200ms,因此 frequency2 被调用了 0 次 | ||
*/ | ||
//有时,这并不是我们想要的结果,我们可能希望最后一次/第一次的事件触发能够被响应 | ||
delay(() => { | ||
expect(frequency2.mock.calls.length).toBe(0); | ||
done(); | ||
}, 100); | ||
}); | ||
|
||
/** | ||
* 每 300 ms 触发一次 down 事件,共触发 3 次 | ||
* 防抖的间隔时间是 200ms,因此 frequency3 被调用了 3次 | ||
*/ | ||
test('debounce/ 事件处理函数被调用3次 ', (done) => { | ||
let myEvent = new EventEmitter(); | ||
/** 高频 down 事件处理函数 */ | ||
const frequency3 = jest.fn(); | ||
/** 防抖间隔时间为 200ms */ | ||
let debounceFrequency = simpleDebounce(frequency3, 200); | ||
myEvent.on('down', () => { | ||
debounceFrequency('hello'); | ||
}); | ||
/** 共触发 3 次 */ | ||
let i = 0; | ||
function delay(callback, interval) { | ||
let timer = setTimeout(() => { | ||
if (i < 3) { | ||
myEvent.emit('down'); | ||
delay(callback, interval); | ||
i++; | ||
} else { | ||
clearTimeout(timer); | ||
callback(); | ||
myEvent.removeAllListeners('down'); | ||
} | ||
}, interval); | ||
} | ||
|
||
/** | ||
* 每 100 ms 触发一次 down 事件 | ||
* 防抖的间隔时间是 200ms,因此 frequency3 被调用了 0 次 | ||
*/ | ||
delay(() => { | ||
expect(frequency3.mock.calls.length).toBe(3); | ||
done(); | ||
}, 300); | ||
}); | ||
|
||
|
||
/** | ||
* 每 300 ms 触发一次 down 事件,共触发 3 次 | ||
* 防抖的间隔时间是 100ms, 第一次触发立即执行, frequency4 被调用了 1次 | ||
*/ | ||
|
||
test('debounce/ 事件处理函数被调用1次 ', (done) => { | ||
let myEvent = new EventEmitter(); | ||
/** 高频 down 事件处理函数 */ | ||
const frequency4 = jest.fn(); | ||
/** 防抖间隔时间为 200ms/立即执行 */ | ||
let debounceFrequency = debounce(frequency4, 200, true); | ||
myEvent.on('down', () => { | ||
debounceFrequency('Yvette'); | ||
}); | ||
/** 共触发 3 次 */ | ||
let i = 0; | ||
function delay(callback, interval) { | ||
let timer = setTimeout(() => { | ||
if (i < 3) { | ||
myEvent.emit('down'); | ||
delay(callback, interval); | ||
i++; | ||
} else { | ||
clearTimeout(timer); | ||
callback(); | ||
myEvent.removeAllListeners('down'); | ||
} | ||
}, interval); | ||
} | ||
|
||
/** | ||
* 每 100 ms 触发一次 down 事件 | ||
* 防抖的间隔时间是 200ms,第一次触发立即执行,frequency4 仅被调用了 1 次 | ||
*/ | ||
delay(() => { | ||
expect(frequency4.mock.calls.length).toBe(1); | ||
done(); | ||
}, 100); | ||
}); |
Oops, something went wrong.