'Is setting interval right way to make sure Ajax call is completed?

I have two input text field and one save button.

<input type="text" id="myInput" />
<input type="text" id="searchResult"/>
<button id="myButton>save</button>

The myInput text field has onchange event which then sends Ajax request to get some data and show the result to searchResult text field.

The save button has click event which validate the input of searchResult text field for empty string and such. If ok then proceed with saving.

$("myInput").change(function() {
    var userInput = $("myInput").val(); //get value from the text field
    var responseText = callAjaxToGetData(userInput):  //XHR request to get some data

    $("searchResult").val( responseText ); //show the XHR result here

});


$("myButton").click(function() {
    var searchResultField = $("searchResult").val(); //get value from the searchResult field
    var isOK = validate(searchResultField);  //check empty string and such

    if(isOK) { saveDataViaAjax(userInput); }
});

Problem

When a user types in some text into the text field and then clicks on "save" button,

  1. onchange event is triggered, callAjaxToGetData() is called. (XHR)

  2. before callAjaxToGetData() is completed and fill in the searchResult text field, myButton onclick event is triggered.

  3. In side of onclick event handler, validation fails because searchResult field is still empty.

  4. callAjaxToGetData() finally finishes and fill in searchResult text field.

Ideally, callAjaxToGetData() is completed first then proceed with the process inside of onclick event so the validation won't fail.

This seems very common case people would face I guess so I'm wondering how you approach this problem?

I am thinking to put interval into onclick event like below (this requires responseText to be a global variable)

$("myButton").click(function() {

   var interval = setInterval(function() { //call every 500ms

       //if responseText is not null that means i know the ajax inside of onchange event is completed for sure.
       if( responseText != null ) {

           clearInterval(interval);

           var searchResultField = $("searchResult").val(); //get value from the searchResult field
           var isOK = validate(searchResultField);  //check empty string and such
    
           if(isOK) { saveDataViaAjax(userInput); }
       }
   }, 500);  
});


Solution 1:[1]

Code below might not be exact but I'd disable the button before ajax and enable after callback returns.

$("myInput").change(function() {
     $("myButton").attr("disabled", "disabled");
     var userInput = $("myInput").val(); //get value from the text field
     var responseText = callAjaxToGetData(userInput, function(data) {

        $("searchResult").val( data); //show the XHR result here
        $("myButton").removeAttr("disabled"); 
     }):
 });

Solution 2:[2]

I think in order to avoid onClick event process goes faster than ajax process in onChange event, setting timer solved the problem.

First I created helper function which checks active ajax connection and calls function that would be otherwise called in onClick event.

helper

function check_pending_process(callback) {
    var interval = setInterval(function() {
        if($.active > 0) {
            //do nothing here
        }
        else {
            //no ajax is running, call the function after 500 ms
            clearInterval(interval);
            setTimeout(function() { window[callback].call() }, 500);
        }    
    }, 100);
}

caller

function processButtonClick() {
    var searchResultField = $("searchResult").val(); //get value from the searchResult field
    var isOK = validate(searchResultField);  //check empty string and such

    if(isOK) { saveDataViaAjax(userInput); }

}

$("#myButton").click(function() {

    check_pending_process("processButtonClick");

});

The 500 ms judgement is based on how long the process of post-ajax in onchange event takes. In my case, post-ajax process inside of onchange event is just put response text into the text field so 500 ms is enough.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DanielEli
Solution 2 Meow