If I get enough users on my application, sending an ajax request with each keystroke is an effective way to bring the server to its knees (not to mention possibly making the client application feel quite sluggish). On implementing a symbol search box with two options (DB Search and Web Api Search). While I am typing the symbol (ex: AAPL - aple stock) in the search box the fetch()
request is sent each time over the network. To avoid it I tried to use setTimeout()
but fetch()
request is sent multiple times, anyway. How to delay/start/debounce fetching the request until user stops typing in input area to send only one fetch()
request?
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
}
Here is the console result:
Here is the network result:
Debounce delays the processing of a function bound to a certain user input event until a certain amount of time has passed. In other words the function is only executed once per specific user input event, even it the event is triggered multiple times.
Solution. To avoid that problem, we better execute a function in proper timing which means after a user stops typing for a while. And setTimeout helps us to do that. The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds.
function debounce(fn, delay) { var timer = null; return function() { var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function() { fn. apply(context, args); }, delay); }; } var SearchBox = React. createClass({ render: function() { return <input type="search" name="p" onChange={this.
The amount of time, in seconds, that elapses before the downlink interfaces are brought up after a state change of the uplink interfaces.
This is commonly solved by debouncing the event; which collapses multiple calls in a given timeframe to just one:
// 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))
<input id="input" placeholder="Type fast here.."/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With