【JS八股文】防抖与节流

576 阅读2分钟

“我叫夯大力,我以为不设置防抖节流就能写出高效的代码,要不是入职第二天就被公司开除了,我差点就信了。”

95aa042631c8b2034af0564049fe563.jpg

来,让我们看看这段罪魁祸首的源代码

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户搜索</title>
</head>
<body>
  <div>
    <label for="unDebounceInput">用户搜索</label>
    <input 
    type="text"
    id="unDebounceInput"
    placeholder="请输入要搜索的用户名字"
    >
  </div>  
  <div>
    <ul id="users">
    </ul>
  </div>
  <script>
  // 获取无序列表元素
  const oUL = document.querySelector('#users');
  // 获取输入框元素
  const oInput = document.getElementById('unDebounceInput');

  oInput.addEventListener('keyup', handleNameSearch)

  // 处理用户搜索的函数
  function handleNameSearch(){
    // 获取输入框的值,并去除前后空格
    let value = oInput.value.trim();
    // 如果输入框为空,清空无序列表的内容并返回
    if (value == '') {
        oUL.innerHTML = '';
        return;
    }
    // 使用fetch向后端接口发送请求,获取用户数据
    fetch('http://localhost:3001/users')
    .then(res => res.json()) // 将响应转换为JSON格式
    .then(users => {
      // 使用filter方法筛选出名字包含输入值的用户
      const filterUsers = users.filter(user => user.name.includes(value));
      // 使用map方法将筛选后的用户数组转换为HTML字符串,并设置为无序列表的内容
      oUL.innerHTML = filterUsers.map(user => 
           `<li>${user.name}</li>`
      ).join(""); 
    })
    .catch(error => {
      console.error('获取用户数据时出错:', error);
    });
  }
  </script>
</body>
</html>

后端数据

{
  "users": [
    {
      "id": "1",
      "name": "夯大力"
    },
    {
      "id": "2",
      "name": "白晶"
    },
    {
      "id": "3",
      "name": "小明"
    }
  ]
  }

分析

这里的后端项目是通过使用json-server来模拟后端服务器处理数据的

步骤

1.创建一个后端文件,并初始化:npm init -y

2.安装json-server :npm i json-server

3.将package.json中script部分改为: "dev": "json-server --watch db.json --port 3001"然后输入:npm run dev 启动

代码分析

  1. HTML部分
  • 创建了一个基本的HTML结构,包含一个输入框和一个无序列表。

  • 输入框用于用户输入搜索关键词,idunDebounceInput

  • 无序列表<ul>用于显示搜索结果,idusers

  1. JavaScript部分:
  • oULoInput分别获取了<ul><input>元素。

  • 为输入框添加了keyup事件监听器,当用户在输入框中输入内容时,会触发handleNameSearch函数。

  • handleNameSearch函数:

    • 获取输入框的值,并去除前后空格。
    • 如果输入框为空,则清空<ul>的内容并返回。
    • 使用fetch向后端接口http://localhost:3001/users发送请求,获取用户数据。
    • 使用filter方法筛选出名字包含输入值的用户。
    • 使用map方法将筛选后的用户数组转换为HTML字符串,并设置为<ul>的内容。
    • 添加了一个catch块来捕获并处理可能的错误。

运行结果

image.png 可以看到,我仅仅是输入了一个小明,结果直接给我整出一列的请求了,这还得了,要是公司的项目,那不得把服务器给整瘫痪了? 接下来我们加入防抖函数,看看

优化后的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户搜索</title>
</head>
<body>
  <div>
    <label for="unDebounceInput">用户搜索</label>
    <input 
    type="text"
    id="unDebounceInput"
    placeholder="请输入要搜索的用户名字"
    >
  </div>  
  <div>
    <ul id="users">
    </ul>
  </div>
  <script>
  // 获取无序列表元素
  const oUL = document.querySelector('#users');
  // 获取输入框元素
  const oInput = document.getElementById('unDebounceInput');
  // 创建一个防抖处理后的搜索函数,延迟时间为500毫秒
  const debounceNameSearch = debounce(handleNameSearch, 500);
  // 为输入框添加keyup事件监听器,当用户输入时触发防抖处理后的搜索函数
  oInput.addEventListener('keyup', debounceNameSearch)

  // 处理用户搜索的函数
  function handleNameSearch(){
    // 获取输入框的值,并去除前后空格
    let value = oInput.value.trim();
    // 如果输入框为空,清空无序列表的内容并返回
    if (value == '') {
        oUL.innerHTML = '';
        return;
    }
    // 使用fetch向后端接口发送请求,获取用户数据
    fetch('http://localhost:3001/users')
    .then(res => res.json()) // 将响应转换为JSON格式
    .then(users => {
      // 使用filter方法筛选出名字包含输入值的用户
      const filterUsers = users.filter(user => user.name.includes(value));
      // 使用map方法将筛选后的用户数组转换为HTML字符串,并设置为无序列表的内容
      oUL.innerHTML = filterUsers.map(user => 
           `<li>${user.name}</li>`
      ).join(""); 
    })
    .catch(error => {
      console.error('获取用户数据时出错:', error);
    });
  }

  // 防抖函数
  function debounce(fn, delay) {
    let id; // 用于存储定时器ID
    return function() {
      // 清除之前的定时器
      clearTimeout(id);
      // 设置新的定时器
      id = setTimeout(() => {
        fn(); // 在延迟时间后调用传入的函数
      }, delay);
    }
  }
  </script>
</body>
</html>

分析

  • debounceNameSearch是一个经过防抖处理的handleNameSearch函数,防抖延迟为500毫秒。

  • 为输入框添加了keyup事件监听器,当用户在输入框中输入内容时,会触发debounceNameSearch函数。

  • 防抖函数:

    • debounce函数是一个高阶函数,接受一个函数fn和一个延迟时间delay作为参数。
    • 返回一个新的函数,当这个新函数被调用时,会清除之前的定时器,并设置一个新的定时器。
    • 如果在delay时间内再次调用新函数,之前的定时器会被清除,新的定时器会被设置。
    • 这样可以确保fn函数在用户停止输入delay毫秒后才被调用,避免了频繁调用导致的性能问题。

    运行结果

image.png 我们只需输入名字的第一个字然后便能查询到结果,可以看到我们从输入到得到结果只进行了两次网络请求。

有了防抖函数,妈妈再也不用担心我被上司炒鱿鱼了

image.png