I have a search bar that on "input", makes an API request based on the value of the search bar. The API response is used to populate search suggestions.
The issue I have is that the API requests are made asynchronously – so the responses are not guaranteed to come back in the same order you sent them. This means the search suggestions could end up being incorrect.
E.g. if I quickly type wh
in the search bar, the page will send two API requests:
/search?q=w
/search?q=wh
If the /search?q=w
request comes back last, then the suggestions will be populated with the results for w
– when it should show the results for wh
instead.
What’s the best way to solve this? I was thinking of storing a timestamp each time I update the search suggestions, and if the function notices a later timestamp, it will not overwrite the suggestions. This should work, but I’m wondering if there’s a nicer / more canonical way to do this.
Here’s a MWE:
let searchBar = document.getElementById("search-bar");
let suggestionsHTML = document.getElementById("suggestions")
searchBar.addEventListener("input", fillSuggestions);
async function fillSuggestions(event) {
let resp = await fetch("/search?" + new URLSearchParams({
q: searchBar.value,
}))
let suggestionsJSON = await resp.json()
suggestionsHTML.innerHTML = ''
for (let result of suggestionsJSON) {
// create new result element & insert into suggestions
addSuggestion(suggestionsHTML, result)
}
}
2
Answers
Adding debounce is a good way to solve this.
And then use it like this, here we are adding a delay of 300 milliseconds
You can read about debounce here.
You can use the debounce technique to trigger API requests after the user stops typing after some time interval. These methods also lower the server load.
You can use this freecodecamp blog: https://www.freecodecamp.org/news/javascript-debounce-example/
if you don’t want to use that method. You can then use the
AbortController
Signal to cancel past requests and initiate new API requests.