zoukankan      html  css  js  c++  java
  • 让你彻底了解什么是节流

    题图 By HymChu From lnstagram

    上一篇文章咱们介绍了防抖,这一篇文章大咱们讨论一下节流,同样咱们看一个需求:页面中有一个文本框,文本框根据用户的输入,发送异步请求关联数据,显示在输入框下面。

    初步实现代码如下:

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title></head><body><input type="text" name="" id="inp"><script>    document.querySelector("#inp").oninput = function(){        console.log("22222")    } </script></body></html>

    不考虑性能的话,功能完全能实现,但是我们看一下控制台,input只要一有输入,就会调用事件函数,我们发现这是不必要的,有的朋友可能想到了上一篇文章的防抖,用防抖也可以实现这个功能,但是用防抖的话有一个小问题,那就是等用户完全输入停止后才去发送异步请求。

    但是我们需要用户输入时候到某个时间节点,不论用户有没有输入完成都发送一次异步请求,用户持续的输入,持续的触发input事件,只要到达某事时间间隔,就发送一次ajax。这样操作会提升用户体验。

    按照上面的描述,咱们来思考一下如何实现上面的代码,首先应该有一个全局变量来获取当前的时间starttime,然后触发input事件的时候,获取触发事件的当前时间currenttime,然后对比两个时间的时间差,如果插值大于等于规定的时间间隔timespace,发送ajax,并且更新starttime,如果小于时间间隔timesapce,不做处理,代码流程图如下:

    按照流程图,代码实现如下:

    <script>var starttime = Date.now();var currenttime = null;var timespace = 3000function ajax(){    console.log("异步请求,渲染dom")}document.querySelector("#inp").oninput = function(){        currenttime = Date.now();    if(currenttime-starttime>timespace){        ajax()        starttime = Date.now();    }else{        console.log("不做处理")    }} </script>

    仔细阅读代码,发现代码又bug,当用户完全输入后,反而不会触发ajax。所以我们要进行处理,添加一个判断,判断用户输入完成后,触发ajax请求,代码修改如下:

    <script>var starttime = Date.now();var currenttime = null;var timespace = 3000// 添加延时器全局变量var timeout = null;function ajax(){    console.log("异步请求,渲染dom")}document.querySelector("#inp").oninput = function(){    currenttime = Date.now();    if(currenttime-starttime>timespace){        clearTimeout(timeout);        starttime = Date.now();        timeout = null;        ajax()    }else{        // 判断有无定时器        if(!timeout){            // 没有定时器的话,打开定时器        timeout = setTimeout(function(){                ajax();                // 调用完成后将timeout清空                timeout = null;            },4000)        }    }}</script>

    这次基本实现了节流的应用,我们看到节流一般和防抖结合使用,因为节流的最后要判断用户是否输入完成。

    上面的代码依然有好多问题,暴露了多个全局变量,不能复用,更改代码如下:

    <script>function ajax(){    console.log("异步请求,渲染dom")}function throttle(callback){    var starttime = Date.now();    var currenttime = null;    var timespace = 3000    var timeout = null;        return function(){        // 用context和event保存调用事件的this和事件对象    var context = this;    var event = arguments[0]    currenttime = Date.now();    if(currenttime-starttime>timespace){        clearTimeout(timeout);        starttime = Date.now();        timeout = null;        // 使callback绑定事件调用对象,和事件对象        callback.call(context,event)    }else{        // 判断有无定时器        if(!timeout){            // 没有定时器的话,打开定时器        timeout = setTimeout(function(){            // 使callback绑定事件调用对象,和事件对象            callback.call(context,event)                // 调用完成后将timeout清空                timeout = null;            },4000)        }    }}}document.querySelector("#inp").oninput = throttle(ajax)</script>

    我们实现了throttle函数,这个函数可以将事件的主要逻辑函数变为一个节流函数,并且我们根据throttle返回的函数最终调用者为inputDom,所以用变量context和event保存调用事件逻辑的this和事件对象,然后将其绑定到callback上面。

    针对上面的过程,我们给节流下一个定义:事件一直触发,我们获取事件触发时间,比较两次触发时间的间隔,当这个时间间隔达到某个阀值的时候,触发事件处理逻辑。

    关联文章:白话防抖。

    以上便是节流的简单实现,如果你有什么建议或者想法欢迎留言。

    欢迎转发、关注、点击好看

    坚持下去就能成功
  • 相关阅读:
    从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理
    从底层谈WebGIS 原理设计与实现(五):WebGIS中通过行列号来换算出多种瓦片的URL 之在线地图
    从底层谈WebGIS 原理设计与实现(四):WebGIS中通过行列号来换算出多种瓦片的URL 之离线地图
    从底层谈WebGIS 原理设计与实现(三):WebGIS前端地图显示之根据地理范围换算出瓦片行列号的原理(核心)
    从底层谈WebGIS 原理设计与实现(二):探究本质,WebGIS前端地图显示之地图比例尺换算原理
    [leetcode]Rotate List
    [leetcode]Remove Element
    [leetcode]Binary Tree Level Order Traversal II
    [leetcode]Populating Next Right Pointers in Each Node II
    [leetcode]Construct Binary Tree from Inorder and Postorder Traversal
  • 原文地址:https://www.cnblogs.com/suoking/p/10519429.html
Copyright © 2011-2022 走看看