Skip to content
Advertisement

Django – AJAX Fetch sends request for each input letter

This might be far from how it should be done, I’m learning on the go and it’s my first time trying something like this.

Problem: Even with the setTimeout function, server sends response for each letter I have written, though I would expect it to wait for user to stop typing and just fetch the finished word(s)

Script in my template:

lookup.addEventListener('keyup', e => {
    
    let searchValue = e.target.value;

    if (searchValue.length > 4){

      setTimeout(() => {
     
        fetch(`{% url 'find_book' %}?param=${e.target.value}` )
          .then(res => res.json())
          .then(data => console.log(data))
          .catch(err => console.log(err))}, 2000);
        }

views.py

@api_view(['GET'])
def find_book(request):

    param = request.GET.get("param")

    if param:
        url = f'https://www.googleapis.com/books/v1/volumes?q=intitle:{param}&key=xxx'
        r = requests.get(url)
        
        if r.status_code == 200:
            data = r.json()
            return Response(data, status=status.HTTP_200_OK)
        else:
            return Response({"error": "Request failed"}, status=r.status_code)
    else:
        return Response({}, status=status.HTTP_200_OK)

Advertisement

Answer

Store timeout id to variable in the scope higher than yours event listner. When event fires up – check if there was a timeout and clear it (which means cancel the request if it wasn’t yet executed)

Example:

let delayedFetch;

lookup.addEventListener('keyup', e => {
    
    let searchValue = e.target.value;

    if (searchValue.length > 4){

      if (delayedFetch) clearTimeout(delayedFetch);

      delayedFetch = setTimeout(() => {
     
        fetch(`{% url 'find_book' %}?param=${e.target.value}` )
          .then(res => res.json())
          .then(data => console.log(data))
          .catch(err => console.log(err))}, 2000);
        }
Advertisement