【问题标题】:Execute a function not more than once every 500 milliseconds while user types continuously在用户连续键入时每 500 毫秒执行不超过一次的功能
【发布时间】:2022-01-31 16:55:12
【问题描述】:

我正在尝试实现诸如自动完成之类的功能,因此当 oninput 事件触发时我正在运行该功能。因为我正在发出获取请求,而不是在每次更改时都运行它,所以我想在(可能)500 毫秒内运行它不超过一次。有没有办法做到这一点?

<body>
   <input id="input" type="text">

   <script>
      function filterData(substr) {
         fetch(url)
           .then(response => response.json())
           .then(data => {
              let filteredData = data.filter(person => person.name.includes(substr));
              print(filteredData);
            })
       }
       document.getElementById("input").oninput = (e) => filterData(e.target.value);
   </script>
</body>

【问题讨论】:

    标签: javascript input timeout fetch-api throttling


    【解决方案1】:

    OP 的描述类似于受限制的行为。为了实现节流进程及其兄弟去抖动进程,有各种可用的库/实现。常用的是lodash和/或underscore.js的方法。

    下一个提供的示例代码使用 OP 最初提供的 filterData 的模拟版本。它显示了 lodash 和两个 基本自定义 throttle/debounce 实现的油门和去抖动的不同行为...

    /*function filterData(substr) {
      fetch(url)
        .then(response => response.json())
        .then(data => {
          let filteredData = data.filter(person => person.name.includes(substr));
          print(filteredData);
        });
    }*/
    function filterData(substr) {
      new Promise((resolve/*, reject*/) => {
      
        setTimeout(() => {
          resolve({
            search: substr,
            matches: [substr + 'Bar', substr + ' bazz', substr + ' Foooo']
          });
        }, 300);
    
      }).then(response => console.log({ response }));
    }
    
    function handleSearch(evt) {
      // console.log('this :', this);
      // // return filterData(this.value);
      return filterData(evt.target.value);
    }
    
    document
      .querySelector("#basicThrottled")
      .addEventListener('input', basicThrottle(handleSearch, 500));
    document
      .querySelector("#basicDebounced")
      .addEventListener('input', basicDebounce(handleSearch, 500));
    
    document
      .querySelector("#lodashThrottled")
      .addEventListener('input', _.throttle(handleSearch, 500));
    document
      .querySelector("#lodashDebounced")
      .addEventListener('input', _.debounce(handleSearch, 500));
    body { margin: 0; }
    [type="search"] { min-width: 24%; max-width: 24%; }
    .as-console-wrapper { min-height: 85%; }
    <input id="basicThrottled" type="search" placeholder="basic throttled ..." />
    <input id="basicDebounced" type="search" placeholder="basic debounced ..." />
    
    <input id="lodashThrottled" type="search" placeholder="lodash throttled ..." />
    <input id="lodashDebounced" type="search" placeholder="lodash debounced ..." />
    
    <script>
    function basicDebounce(proceed, delay = 300, target) {
      let timeoutId = null;
    
      return function debounced(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(proceed.bind(target ?? this), delay, ...args);
      };
    }
    function basicThrottle(proceed, threshold = 200, target) {
      let timeoutId = null;
      let referenceTime = 0;
    
      return function throttled(...args) {
        const currentTime = Date.now();
    
        if (currentTime - referenceTime >= threshold) {
          clearTimeout(timeoutId);
    
          referenceTime = currentTime;
          const trigger = proceed.bind((target ?? this), ...args);
    
          timeoutId = setTimeout((() => {
    
            referenceTime = 0;
            trigger();
    
          }), threshold);
    
          trigger();
        }
      };
    }
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

    【讨论】:

      【解决方案2】:

      您好,请使用此代码超时

          var timeoutId
      function autoComplete(substr)
      {
          
              // stop previous timeouts
              clearTimeout(timeoutId)
              timeoutId = setTimeout(function () {
               fetch(url)
                 .then(response => response.json())
                 .then(data => {
                    let filteredData = data.filter(person => 
            person.name.includes(substr));
                    print(filteredData);
                  })
             });
               }, 1000);
          
      }    
      

      【讨论】:

        猜你喜欢
        • 2016-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多