手写节流函数

简介: JS查漏补缺系列是我在学习JS高级语法时做的笔记,通过实践费曼学习法进一步加深自己对其的理解,也希望别人能通过我的笔记能学习到相关的知识点。这一次我们来试着手写节流函数

节流的基本实现逻辑
image.png

基本实现


console.log(`发送了第${++counter}次网络请求`)

}

// 节流处理
inputEl.oninput = throttle(inputChange, 2000)

function throttle(fn, interval, options) {
// 1.记录上一次的开始时间
let lastTime = 0

// 2.事件触发时, 真正执行的函数
const _throttle = function() {

// 2.1.获取当前事件触发时的时间
const nowTime = new Date().getTime()

// 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长时间需要去触发函数
const remainTime = interval - (nowTime - lastTime)
if (remainTime <= 0) {
  // 2.3.真正触发函数
  fn()
  // 2.4.保留上次触发的时间
  lastTime = nowTime
}

}

return _throttle
}

功能优化——leading实现
:::info
有时候我们不想第一次输入的时候就发送请求,这时候我们最好做一个可选项供用户选择第一次的时候是否发送请求(leading: true/false)
:::

function throttle(fn, interval, options = { leading: true }) {
const { leading } = options
let lastTime = 0

const _throttle = function() {

const nowTime = new Date().getTime()
if (!lastTime && !leading) lastTime = nowTime

const remainTime = interval - (nowTime - lastTime)
if (remainTime <= 0) {
  fn()
  lastTime = nowTime
}

}
return _throttle
}

功能优化——trailing 实现
:::info
用户在10s内输出了一些内容后停止输出,因为 “ 与上一次发送请求时的间隔不为10s“ 而没有发送请求
用户需求:想要在停止输出的10s后发送请求,即使最后一次输出没有达到与上一次发送请求的间隔为10s的要求
:::

function throttle(fn, interval, options = { leading: true, trailing: false }) {
const { leading, trailing } = options
let lastTime = 0
let timer = null


const _throttle = function() {

const nowTime = new Date().getTime()
if (!lastTime && !leading) lastTime = nowTime

const remainTime = interval - (nowTime - lastTime)
if (remainTime <= 0) {
  // 在最后一次达到要求的情况下是不需要加上定时器的,要取消掉
  if (timer) {
    clearTimeout(timer)
    timer = null
  }
  fn()
  lastTime = nowTime
  return  // return是为了防止被加上下面的定时器
}

if (trailing && !timer) {
  timer = setTimeout(() => {
    timer = null
    lastTime = !leading ? 0: new Date().getTime()
    fn()
  }, remainTime)
}

}

return _throttle
}

功能优化——this、参数改进
:::info
与防抖中this、参数改进使用的方法是一样的,用apply进行绑定this、arg,用剩余函数...arg接收参数
:::

function throttle(fn, interval, options = { leading: true, trailing: false }) {
const { leading, trailing } = options
let lastTime = 0
let timer = null
// 用剩余函数...arg接收参数
const _throttle = function(...args) {

const nowTime = new Date().getTime()
if (!lastTime && !leading) lastTime = nowTime

const remainTime = interval - (nowTime - lastTime)
if (remainTime <= 0) {
  if (timer) {
    clearTimeout(timer)
    timer = null
  }

  //用apply进行绑定this、arg
  fn.apply(this, args)
  lastTime = nowTime
  return
}

if (trailing && !timer) {
  timer = setTimeout(() => {
    timer = null
    lastTime = !leading ? 0: new Date().getTime()
    fn.apply(this, args)
  }, remainTime)
}

}

return _throttle
}

功能优化——取消功能
:::info
场景:用户在输入东西之后防抖函数发送请求之前按到退出键退出了界面或按了取消按钮,这时我们就不用再发送请求
:::


// 在原来的外部script代码中添加取消功能的代码
_throttle.cancel = function() {

if(timer) clearTimeout(timer)
timer = null
lastTime = 0

}

功能优化——函数返回值
:::info
使用Promise来实现,resolve( ) 将结果进行回调出去
:::

function throttle(fn, interval, options = { leading: true, trailing: false }) {
const { leading, trailing, resultCallback } = options
let lastTime = 0
let timer = null

const _throttle = function(...args) {

return new Promise((resolve, reject) => {
  const nowTime = new Date().getTime()
  if (!lastTime && !leading) lastTime = nowTime

  const remainTime = interval - (nowTime - lastTime)
  if (remainTime <= 0) {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }

    const result = fn.apply(this, args)
    if (resultCallback) resultCallback(result)
    resolve(result)
    lastTime = nowTime
    return
  }

  if (trailing && !timer) {
    timer = setTimeout(() => {
      timer = null
      lastTime = !leading ? 0: new Date().getTime()
      const result = fn.apply(this, args)
      if (resultCallback) resultCallback(result)
      resolve(result)
    }, remainTime)
  }
})

}

_throttle.cancel = function() {

if(timer) clearTimeout(timer)
timer = null
lastTime = 0

}

return _throttle
}

目录
相关文章
|
前端开发
node express 给前端返回图片流
node express 给前端返回图片流
node express 给前端返回图片流
Threejs创建天空和太阳
这篇文章讲解了如何使用Three.js中的Sky组件来创建真实的天空与太阳效果,包括调整天空的颜色、太阳的位置以及实现大气散射等技巧。
589 3
|
Web App开发 缓存 监控
如何使用 Chrome DevTools 的 Performance 面板进行页面加载性能分析?
如何使用 Chrome DevTools 的 Performance 面板进行页面加载性能分析?
|
前端开发 JavaScript
宏任务和微任务在浏览器渲染过程中的执行顺序
宏任务和微任务是浏览器事件循环中的两种任务类型。宏任务包括整体代码块、setTimeout等,微任务有Promise.then、MutationObserver等。每个宏任务执行完毕后,会先执行完所有微任务,再进行下一轮渲染或执行下一个宏任务。
|
缓存 前端开发 JavaScript
前端性能优化:实用技巧与策略
本文介绍了前端性能优化的关键技巧与策略,涵盖减少HTTP请求、利用浏览器缓存、压缩资源文件、异步加载非关键资源、优化CSS和JavaScript、减少DOM操作、谨慎使用Web字体、优化第三方脚本、使用服务工作者以及性能监测和分析等方面,帮助提升用户体验和搜索引擎优化效果。
|
SQL 缓存 关系型数据库
MySQL高级篇——关联查询和子查询优化
左外连接:优先右表创建索引,连接字段类型要一致、内连接:驱动表由数据量和索引决定、 join语句原理、子查询优化:拆开查询或优化成连接查询
MySQL高级篇——关联查询和子查询优化
vue2 自定义 v-model (model选项的使用)
vue2 自定义 v-model (model选项的使用)
1760 1
|
JavaScript 安全 前端开发
TypeScript 基础学习笔记:interface 与 type 的异同
TypeScript 基础学习笔记:interface 与 type 的异同
465 0
|
JavaScript
vue常用正则表达式判断身份证格式
这两个正则表达式分别用于验证18位和15位身份证号码。请注意,正则表达式只能用于初步验证身份证格式是否正确,不能验证身份证号码是否真实有效。在实际应用中,还需要进行进一步的校验,例如校验身份证的校验位等。
691 0
|
JavaScript 前端开发 UED
js的节流
js的节流
267 0