继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

节流模式

为爱心太软
关注TA
已关注
手记 170
粉丝 1.4万
获赞 860

节流模式

屏蔽重复的业务逻辑,只执行最后一次的操作,就叫做节流模式。

使用场景

节流模式的核心思想是创建计时器,延迟程序的执行。
比如一些常见的事件,scroll、resize、dragover等,这类事件属于高频触发事件,会多次调用事件处理程序。

例子:

let n = 0;
window.onresize = () => {
  console.log(n++);
};

打开浏览器的开发者模式,可以发现,当浏览器的窗口进行缩放时,会多次打印数字。
我们可以用节流模式去解决这个问题。

例子:

// 创建一个节流器
const throttle = (() => {
  let timer = null;

  return ({ handle = () => {}, time = 300 } = {}) => {
    // 清除计时器句柄
    clearTimeout(timer);

    // 创建计时器句柄,延迟函数的执行
    timer = setTimeout(() => {
      handle();
    }, time);
  };
})();

// 测试节流器
let n = 0;
window.onresize = () => {
  throttle({
    handle: () => {
      console.log(n++);
    },
    time: 500,
  });
};

优化之后的代码,每缩放一次浏览器的窗口,只会打印一个数字。
除了对事件进行优化,节流模式的用处非常广泛,试想一个这样的场景:有一行文字,当鼠标滑过某些特殊字符的时候,会展示提示内容。

例子:

<style>
  span {
    background-color: beige;
    font-size: 12px;
    display: none;
  }
</style>

<p><strong>*宋仁宗赵祯*</strong>,初名赵受益,宋朝第四位皇帝。</p>
<span>公元1010年5月30日至1063年4月30日</span>

<script>
  const txt = document.querySelector("strong");
  const tip = document.querySelector("span");

  txt.addEventListener("mouseenter", () => {
    tip.style.display = "block";
  });
  txt.addEventListener("mouseleave", () => {
    tip.style.display = "none";
  });
</script>

例子中,按正常的交互,鼠标移入“宋仁宗赵祯”时就展示提示内容,移除时提示内容消失。如果用户只是无意间移入和移除,冒然展示提示内容显得很不友好,此时,我们也可以使用节流模式延迟程序的执行。

例子:

<style>
  span {
    background-color: beige;
    font-size: 12px;
    display: none;
  }
</style>

<p><strong>*宋仁宗赵祯*</strong>,初名赵受益,宋朝第四位皇帝。</p>
<span>公元1010年5月30日至1063年4月30日</span>

<script>
  const txt = document.querySelector("strong");
  const tip = document.querySelector("span");

  // 节流器
  const throttle = (() => {
    let timer = null;
    return ({ handle = () => {}, time = 300 } = {}) => {
      // 清除计时器句柄
      clearTimeout(timer);

      // 创建计时器句柄,延迟函数的执行
      timer = setTimeout(() => {
        handle();
      }, time);
    };
  })();

  txt.addEventListener("mouseenter", () => {
    throttle({
      handle: () => {
        tip.style.display = "block";
      },
      time: 500,
    });
  });

  txt.addEventListener("mouseleave", () => {
    throttle({
      handle: () => {
        tip.style.display = "none";
      },
      time: 500,
    });
  });
</script>

做过前端埋点的程序员应该都清楚,我们并不会每触发一次事件就发送一次请求,而是要等到触发次数到达一定数量时(或者依据停留页面时间),才发送一次请求,这里面其实也用到了节流模式。

例子:

<label>姓名:</label>
<select>
  <option value="Tom">Tom</option>
  <option value="Amy">Amy</option>
</select>
<br />
<label>职业:</label>
<select>
  <option value="Teacher">Teacher</option>
  <option value="Police">Police</option>
</select>
<br />
<label>国籍:</label>
<select>
  <option value="China">China</option>
  <option value="Japan">Japan</option>
</select>

<script>
  const select = document.querySelectorAll("select");

  // 利用节流模式,统一发送数据
  const keepLog = (() => {
    let list = [];
    const max = 3;
    const sendLog = () => {
      console.log(`发送数据:${list}`);
      list = [];
    };

    return ({ id = `Log${Date.now()}`, etype = "", context = "" } = {}) => {
      list.push(`${id}||${etype}||${context}`);
      if (list.length >= max) {
        sendLog();
      }
    };
  })();

  // 测试
  [...select].forEach((item) => {
    item.addEventListener("change", (e) => {
      keepLog({
        etype: "change",
        context: e.currentTarget.value,
      });
    });
  });
</script>

如有错误,欢迎指正,本人不胜感激。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP