【问题标题】:How to delay/start/debounce fetching data until user stops typing?如何延迟/开始/去抖动获取数据,直到用户停止输入?
【发布时间】:2019-06-15 11:59:27
【问题描述】:

如果我的应用程序有足够多的用户,每次击键都发送一个 ajax 请求是一种让服务器瘫痪的有效方法(更不用说可能让客户端应用程序感觉很慢)。关于实现具有两个选项(DB 搜索和 Web Api 搜索)的符号搜索框。当我在搜索框中输入符号(例如:AAPL - aple stock)时,每次都会通过网络发送fetch() 请求。为了避免它,我尝试使用setTimeout(),但fetch() 请求被发送多次,无论如何。如何延迟/开始/去抖动获取请求,直到用户停止在输入区域输入以仅发送一个 fetch() 请求?

HTML:

<label for="symbolTags">Symbol: </label>
  <input type="text" id="symbolTags" name="symbol">

  <label for="api">Select Search Api: </label>
  <select id="api" name="routes_api">
    <option value="search">Web Search Api</option>
    <option value="dbsearch">DB Search Api</option>
  </select>

JavaScript:

const symbolTags = document.querySelector('#symbolTags')
const symbolTagsOptions = document.querySelector('#api')

const urlsObject = {
  dbsearch: '/dbsearch/',
  search: '/search/'
}

symbolTags.oninput = function () {
  let symbolTagsOptionsValue = symbolTagsOptions.value
  let arg = urlsObject[symbolTagsOptionsValue]

  // Init a timeout variable to be used below
  let timeout = null
  // Clear the timeout if it has already been set.
  // This will prevent the previous task from executing
  // if it has been less than <MILLISECONDS>
  clearTimeout(timeout)
  // Make a new timeout set to go off in 2000ms
  timeout = setTimeout(function () {
    requestSymbolSearch(arg)
  }, 2000)
}

function requestSymbolSearch(arg) {
  getData(arg)
    .then(data => {
      console.log(data)
      $('#symbolTags').autocomplete({
        source: data.map(item => item.symbol),
        autoFocus: true
      })
    })
    .catch(error => console.error('Error:', error))
}

function getData(url) {
  let curValueSymbol = symbolTags.value
  let urlPlus = `${url}${curValueSymbol}`
  console.log(urlPlus)
  return fetchData(urlPlus)
}

async function fetchData(urlPlus) {
  const dataResponse = await fetch(urlPlus)
  const dataJson = await dataResponse.json()
  return dataJson
}

这是控制台结果:

这是网络结果:

【问题讨论】:

  • 如何使用最小输入长度,例如fetch只有在输入n个字符后才会发出请求
  • @brk 问题,它也可能是一个字母符号

标签: javascript node.js


【解决方案1】:

这通常由debouncing事件解决;将给定时间范围内的多次调用折叠为只有一次

// Debounce function from: https://stackoverflow.com/q/24004791/1814486
const debounce = (func, wait, immediate) => {
  let timeout

  return function() {
    const context = this, args = arguments
    const later = function() {
      timeout = null
      if (!immediate) func.apply(context, args)
    }

    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func.apply(context, args)
  }
}
  
// If there's not another `input` within 500ms log the value,
// otherwise ignore the event.
document.querySelector('#input').addEventListener('input', debounce(() => {
  console.log(input.value)
}, 500))
&lt;input id="input" placeholder="Type fast here.."/&gt;

【讨论】:

  • keyup 事件运行良好,但我试图实现 oninput 事件由于某种原因它不起作用
  • 什么是symbolTabs?它是&lt;input&gt; 元素吗?
  • 刚刚在问题中添加了 HTML
  • @JohnJohn 已编辑。
猜你喜欢
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
相关资源
最近更新 更多