2

I am a bit bewildered. I have a function that calls an ajax search on keyup below.

$(document).on('keyup', '#search', function(e) {
        $("#showPending").html("");
        if ($('#showPending').is(':empty')){
            if ( this.value.length > 2  ) {

                var search = $("#search").val();
                loadsearch(search);
            }
        }
    });

Everything works great except if the user types a search parameter quickly he/she will get duplicate records appended to the #showPending table. If they type slowly they will get perfect results. I was under the impression the loadsearch function will not be called until after the #showpending element is empty because it is a synchronous function. Any ideas what I am doing wrong? Cheers! update: load search function (minimized) below:

function loadsearch(search){

    $("#showPending").html("");
    
    $.ajax({
    url: "server-calls/load-search.php?callback=?",
    type: "GET",
    data: {search: search},
    dataType: "jsonp",
    crossDomain: true,
    success: function (data, status) {
            for(var i = 0; i < data.length; i++) {
            var obj = data[i];
                
            $("#showPending").append('<a href="javascript:void(0);">SEARCH RESULTS </a>');
            }
        
        }                                   
    });     
}
5
  • 1
    Can you show the code of loadsearch? Commented Mar 21, 2021 at 17:57
  • You are removing the content of #showPending right before checking if empty. i.e. it will always be empty. I am not sure this resolves all your issues, but it is definitely not something you want to do. Commented Mar 21, 2021 at 18:01
  • added the load search function Commented Mar 21, 2021 at 18:03
  • 2
    Read up on how to "throttle" or "debounce" in js to account for faster typing and cut down on requests for every key stroke Commented Mar 21, 2021 at 18:04
  • @ZoliSzabó yeah, thats what I expected. I added that extra check to try to make sure the element is empty before ajaxing in more results. ie. I don't want duplicates Commented Mar 21, 2021 at 18:05

1 Answer 1

1

You can abort the previous XHR at the beginning of calling loadsearch, so that the prior request doesn't go to its success handler:

let request;
function loadsearch(search){
    request?.abort();
    $("#showPending").html("");
    
    request = $.ajax({
        // ...

You can also send out a request only after a certain amount of time has passed since the last input, maybe 500ms:

let timeout;
$(document).on('keyup', '#search', function (e) {
    $("#showPending").html("");
    if ($('#showPending').is(':empty')) {
        if (this.value.length > 2) {
            var search = $("#search").val();
            clearTimeout(timeout);
            timeout = setTimeout(() => loadsearch(search), 500);
        }
    }
});

For the best experience, I'd recommend using both approaches together.

Sign up to request clarification or add additional context in comments.

2 Comments

This works perfect! Thank you so much. Would I be correct in assuming that .html() is in fact asynchronous?? (and not synchronous as most stackoverflow users say?)
No, html is synchronous. The only async action here is the $.ajax

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.