手写节流函数
将自己的理解和知识点写在代码注释中.(习惯了)
throttle-v1-基本实现
function throttle(fn, interval = 1000) {
// 1.记录上一次的开始时间
let lastTime = 0
const _throttle = function(...args) {
// 2.获取每次触发的时间
const nowTime = new Date().getTime()
console.log('现在时间:', nowTime);
// 3.剩余时间
const remainTime = interval - (nowTime - lastTime)
console.log('剩余时间:', remainTime);
if(remainTime <= 0) {
fn.apply(this, args)
// 4.保留上次触发的时间
lastTime = nowTime
}
}
return _throttle
}
throttle-v2-leading实现
// lead头部,默认执行
function throttle(fn, interval = 1000, options = { leading: true, trailing: false }) {
// 1.记录上一次的开始时间
let lastTime = 0
const { leading, trailing } = options
const _throttle = function(...args) {
// 2.获取每次触发的时间
const nowTime = new Date().getTime()
// 2.1对第一次输入要不要执行
if(!lastTime && !leading) {
lastTime = nowTime // (nowTime - lastTime)为0,第一次进入等待interval后执行
}
// 3.剩余时间
const remainTime = interval - (nowTime - lastTime)
if(remainTime <= 0) {
fn.apply(this, args)
// 4.保留上次触发的时间
lastTime = nowTime
}
}
return _throttle
}
throttle-v3-trailing实现
// trail尾部,默认不执行
function throttle(fn, interval = 1000, options = { leading: true, trailing: false }) {
// 1.记录上一次的开始时间
let lastTime = 0
let timer = null
const { leading, trailing } = options
const _throttle = function(...args) {
// 2.获取每次触发的时间
const nowTime = new Date().getTime()
// 2.1对第一次输入要不要执行
if(!lastTime && !leading) {
lastTime = nowTime // (nowTime - lastTime)为0,第一次进入等待interval后执行
}
// 3.剩余时间
const remainTime = interval - (nowTime - lastTime)
if(remainTime <= 0) {
if(timer){
clearTimeout(timer)
timer = null
}
fn.apply(this, args)
// 4.保留上次触发的时间
lastTime = nowTime
return // 刚开始执行或时间刚好等于interval时,没有必要加定时器,不执行下面的代码
}
if(trailing && !timer) { // timer为null会进去
timer = setTimeout(() => {
timer = null
lastTime = 0
fn.apply(this, args)
}, remainTime);
}
}
return _throttle
}
throttle-v4-取消功能
// trail尾部,默认不执行
function throttle(fn, interval = 1000, options = { leading: true, trailing: false }) {
// 1.记录上一次的开始时间
let lastTime = 0
let timer = null
const { leading, trailing } = options
const _throttle = function(...args) {
// 2.获取每次触发的时间
const nowTime = new Date().getTime()
// 2.1对第一次输入要不要执行
if(!lastTime && !leading) {
lastTime = nowTime // (nowTime - lastTime)为0,第一次进入等待interval后执行
}
// 3.剩余时间
const remainTime = interval - (nowTime - lastTime)
if(remainTime <= 0) {
if(timer){
clearTimeout(timer)
timer = null
}
fn.apply(this, args)
// 4.保留上次触发的时间
lastTime = nowTime
return // 刚开始执行或时间刚好等于interval时,没有必要加定时器,不执行下面的代码
}
if(trailing && !timer) { // timer有值
timer = setTimeout(() => {
timer = null
lastTime = 0
fn.apply(this, args)
}, remainTime);
}
}
_throttle.cancel = () => {
if(timer) clearTimeout(timer)
timer = null
lastTime = 0
}
return _throttle
}
throttle-v5-函数返回值
// trail尾部,默认不执行
function throttle(fn, interval = 1000, options = { leading: true, trailing: false }, resultCallback) {
// 1.记录上一次的开始时间
let lastTime = 0
let timer = null
const { leading, trailing } = options
const _throttle = function(...args) {
// 2.获取每次触发的时间
const nowTime = new Date().getTime()
// 2.1对第一次输入要不要执行
if(!lastTime && !leading) {
lastTime = nowTime // (nowTime - lastTime)为0,第一次进入等待interval后执行
}
// 3.剩余时间
const remainTime = interval - (nowTime - lastTime)
if(remainTime <= 0) {
if(timer){
clearTimeout(timer)
timer = null
}
const result = fn.apply(this, args)
if(result && resultCallback && typeof resultCallback === 'function'){
resultCallback(result)
}
// 4.保留上次触发的时间
lastTime = nowTime
return // 刚开始执行或时间刚好等于interval时,没有必要加定时器,不执行下面的代码
}
if(trailing && !timer) { // timer有值
timer = setTimeout(() => {
timer = null
lastTime = 0
const result = fn.apply(this, args)
if(result && resultCallback && typeof resultCallback === 'function'){
resultCallback(result)
}
}, remainTime);
}
}
_throttle.cancel = () => {
if(timer) clearTimeout(timer)
timer = null
lastTime = 0
}
return _throttle
}
html文件(对节流进行测试)
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" placeholder="请输入商品名~" />
<button id="btn">取消</button>
<!-- <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.2/underscore-umd-min.js"></script> -->
<!-- <script src="./06_throttle-v1-基本实现.js"></script> -->
<script src="./07_throttle-v2-leading实现.js"></script>
<!-- <script src="./08_throttle-v3-trailing实现.js"></script> -->
<!-- <script src="./09_throttle-v4-取消功能.js"></script> -->
<!-- <script src="./10_throttle-v5-函数返回值.js"></script> -->
<script>
const inputEl = document.querySelector("input");
let index = 0;
const inputFn = function (event) {
console.log(`执行第${++index}次`, this, event);
return "aaaaa";
};
// const newInputFn = _.throttle(inputFn, 2000);
// 实现自己的节流函数
const newInputFn = throttle(
inputFn,
3000,
{
leading: false,
trailing: true,
},
(res) => {
console.log("拿到函数的返回值:", res);
}
);
inputEl.addEventListener("input", newInputFn);
// 取消功能
const btnEl = document.querySelector("#btn");
btnEl.addEventListener("click", () => {
newInputFn.cancel();
});
</script>
</body>
</html>