1

With jquery & ajax in a Symfony application, a button click is intended to retrieve a couple of properties of an entity. The first click of the button returns undefined; further clicks retrieve the expected values. How to get it the first time?

Script snippet:

    $("#contact_household_button").click(function() {
        var houseId = $("#contact_household").val();
        if (houseId !== "") {
            var url = "/app_dev.php/household/contact/" + houseId;
            $.get(url, function(data) {
                $("#household_store").data(data);
            })
            var household = $("#household_store");
            var head = household.data('head');
            alert(houseId + ": " + head);
        }
    });

Sample response provided by get():

{"id":8607,"head":"Some Person"}

First click yields

8607: undefined

2 - n clicks yield

8607 : Some Person

geoB
  • 4,578
  • 5
  • 37
  • 70
  • possible duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – Fabrício Matté Sep 08 '13 at 00:09
  • Asynchronous callbacks are not executed synchronously, you know. – Fabrício Matté Sep 08 '13 at 00:10
  • Indeed. How does this explain that the length of the data retrieved in all get()s (including the first) is 1, yet `head` is undefined on click #1? – geoB Sep 08 '13 at 00:25
  • I (a relative noob on ajax) get it. I'll try another approach. – geoB Sep 08 '13 at 00:30

1 Answers1

1

$.get is asynchronous.

That means, its callback function will execute sometime in the future, when the request successfully fetches a response. The code below the $.get call executes synchronously, it does not wait for asynchronous operations to finish.

Code that depends on the data asynchronously retrieved through $.get must be executed/called from inside the $.get callback:

        $.get(url, function(data) {
            $("#household_store").data(data);
            //got response, now you can work with it
            var household = $("#household_store");
            var head = household.data('head');
            alert(houseId + ": " + head);
        });

If you prefer, it is also possible to attach callbacks by using the $.Deferred-compatible jqXHR methods:

        $.get(url).done(function(data) {
            $("#household_store").data(data);
            //got response, now you can work with it
            var household = $("#household_store");
            var head = household.data('head');
            alert(houseId + ": " + head);
        });

I guess you may already have figured why you would need "2 clicks" for it to work by now, but anyway, here's the execution flow of your posted code (paragraphs to denote synchronous blocks, indentation for Ajax request start/end):

>>> Clicks button
    >>> sends Ajax request
>>> Alerts undefined as response hasn't been received yet

    >>> some milliseconds in the future receives response from Ajax call, sets element data

>>> Clicks button again
    >>> sends Ajax request again
>>> Uses the data set from the previous request

    >>> sometime later receives data from request, set element data

Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166