-1

I use jquery to retrieve via ajax request a number of values that I use to populate input fields. After retrieving these fields I need to use their new values in another ajax call, but I see that I get values that were in the field before my ajax call.

$("#clickme").function(e) {
   e.preventDefault()
   retrieveValues()
   compareValues()
}

function retrieveValues {
    paramList = {}

    ..... snip .....

    $.ajax({
    url: myControllerAction,
        type: "POST",
        dataType: "json",
        data: JSON.stringify(paramList),
        contentType: "application/json; charset=utf-8",
        success: function (result) {
                $("#myFieldOne").val(result["myFieldOne"]);
                $("#myFieldOne").val(result["myFieldOne"]);
                $("#myFieldThree").val(result["myFieldThree"]);
            }
        },
        error: function () {
            alert("error");
        }
    });

function compareValues {
    paramList = {}
    paramList["myFieldOne"] = $("#myFieldOne").val();
    paramList["myFieldTwo"] = $("#myFieldTwo").val();
    paramList["myFieldThree"] = $("#myFieldThree").val();
    paramList = {}

    ..... snip ....

    $.ajax({
    url: myOtherControllerAction,
        type: "POST",
        dataType: "json",
        data: JSON.stringify(paramList),
        contentType: "application/json; charset=utf-8",
        success: function (result) {

            .....
            some Business Logic
            .....

            }
        },
        error: function () {
            alert("error");
        }
    });
}

Before clicking on "clickme" I have

<input name="myFieldOne" id="myFieldOne" value="default value #1">
<input name="myFieldTwo" id="myFieldTwo" value="default value #2">
<input name="myFieldThree" id="myFieldThree" value="default value #3">

and the function retrieveValues SHOULD SET these three fields with new values "New Value #1", "New Value #2", "New Value #3".

After returning from retrieveValues() I call compareValues(), but Jquery objects still contain default values. I seems that field values are actually changed only after the end of the click event. Function compareValues() sends wrong data on the first click, values are compared wrong, then if I click again on "clickme" values are compared right.

Is there any way to correct this and have jquery recognize on the fly my new values in input fields?

Francesco

kranz
  • 599
  • 1
  • 6
  • 23
  • 1
    Ajax is async, you should call `compareValues()` once ajax is done, calling it e.g from ajax success callback – A. Wolff May 26 '14 at 10:15
  • ajax calls are asynchronous.. so when you run the `compareValues` the ajax call from `retrieveValues` has not completed so you are still seeing the old values in the fields.. – Gabriele Petrioli May 26 '14 at 10:15

3 Answers3

2

Ajax calls by default is asynchronous. To use your compareValues function after retrieveValues you can call compareValues in success handler in retrieve or make retrieveValues syncronous by setting ajax option async:false (default is: true)

Example 1: Use callback function

function retrieveValues (callback) {
    paramList = {}

    ..... snip .....

    $.ajax({
    url: myControllerAction,
        type: "POST",
        dataType: "json",
        data: JSON.stringify(paramList),
        contentType: "application/json; charset=utf-8",
        success: function (result) {
                $("#myFieldOne").val(result["myFieldOne"]);
                $("#myFieldOne").val(result["myFieldOne"]);
                $("#myFieldThree").val(result["myFieldThree"]);

                //CALL callback function.
                if(typeof callback === 'function') callback();
            }
        },
        error: function () {
            alert("error");
        }
    });

}

Example 2: Set ajax option async to false

function retrieveValues () {
paramList = {}

..... snip .....

$.ajax({
url: myControllerAction,
    type: "POST",
    async:false //SET ASYNC TO FALSE
    dataType: "json",
    data: JSON.stringify(paramList),
    contentType: "application/json; charset=utf-8",
    success: function (result) {
            $("#myFieldOne").val(result["myFieldOne"]);
            $("#myFieldOne").val(result["myFieldOne"]);
            $("#myFieldThree").val(result["myFieldThree"]);
        }
    },
    error: function () {
        alert("error");
    }
});
Epsil0neR
  • 1,676
  • 16
  • 24
  • I accept the solution of calling compareValues in the success handler. ANyway I do not fully understand the "async-ness" of ajax call. If I debug the entire process in Chrome I can see that field values are filled only after exiting the "click" handler; so it seems it is actually syncronous, things happen only at the end, and not "as soon as ajax call finishes"... How this can be explained? – kranz May 26 '14 at 19:36
0

The issue is due to asynchronous response from ajax call. At the time when the other function fetches the values, the ajax call does not return the updated values, and hence the stale values are read.

One way to solve this is to make the call synchronous:

$.ajax({
    url: myControllerAction,
        type: "POST",
        dataType: "json",
        async:false,
         --- rest of the code ----
Karan Punamiya
  • 8,603
  • 1
  • 26
  • 26
0

That is because the an Ajax call is async. So when you call compareValues the retrieveValues is not finished yet.

$("#clickme").function(e) {
   e.preventDefault();
   retrieveValues(); // just called, ajax not finished
   compareValues(); // called right after retrieveValues
}

You could change your code, so that retrieveValues returns a Promise.

function retrieveValues {
    paramList = {}

    ..... snip .....
    // RETURN an Ajax Promise
    return $.ajax({
    url: myControllerAction,
        type: "POST",
        dataType: "json",
        data: JSON.stringify(paramList),
        contentType: "application/json; charset=utf-8",
        success: function (result) {
                $("#myFieldOne").val(result["myFieldOne"]);
                $("#myFieldOne").val(result["myFieldOne"]);
                $("#myFieldThree").val(result["myFieldThree"]);
            }
        },
        error: function () {
            alert("error");
        }
    });
}

Now you can use .done() on the return value of retrieveValues.

retrieveValues().done(function() { compareValues(); });
Luke
  • 8,235
  • 3
  • 22
  • 36