Murat
Murat

Reputation: 445

nested ajax parent completed before child had finished

$.ajax(
        {
            type: 'POST',
            url: '@Url.Action("EkranListeleSektor")',
            dataType: 'json',
            async: false, //added async later, no changes
            data: { sektorID: $("#ekranSektorID").val() },

            success: function (items) {
                $.each(items, function (i, ekranlar) {

                    $.ajax({
                        type: 'POST',
                        url: '@Url.Action("IlAdGetir")',
                        dataType: 'json',
                        data: { id: ekranlar.il },
                        success: function (ilAd) {
                            strIlAd = ilAd;
                        },
                        error: function (ex) {
                            alert('İl isim çekilemedi.' + ex);
                        }
                    });


                    $.ajax({
                        type: 'POST',
                        url: '@Url.Action("IlceAdGetir")',
                        dataType: 'json',
                        data: { id: ekranlar.ilce },

                            success: function (ilceAd) {
                                alert(ilceAd);
                            strIlceAd = ilceAd;
                        },
                        error: function (ex) {
                            alert('İlce isim çekilemedi.' + ex);
                        }
                    });

                    divContent += '<label class="styledLabel">' +
                        ' <img src=' + (ekranlar.resimURL).replace('~', '') + ' style="height:150px;width:150px;"/>' +
                        '<input type="checkbox" id="' + ekranlar.ekranID + '" name="' + ekranlar.ekranAd + '" value="' + fiyat +
                                    '" class="styledCheck">' + '<br /><span>Ekran İsim: </span><span class="spanEkranAd">' + ekranlar.ekranAd +
                                    '</span><br /><span>' + 'Günlük Fiyat' + ': </span>' + fiyat + '<br /><span>Ekran Boyutu: </span><span class="spanEkranBoyut">'
                                    + ekranlar.ekranBoyutID + '"</span> <br/>' +
                                    '<span class="spanIl">' + strIlAd + '</span><br/> <span class="spanIlce">' + strIlAd + '</span> </label>';

                    $("#imgDiv").append(divContent);
                });
            }, error: function (ex) {
                alert('Ekranlar Çekilemedi.' + ex);
            }
        });
    }

my action part worked correctly i can see coming data with alert and debugger but "EkranListeleSektor" completed before nested "IlAdGetir" or "IlceAdGetir" starting so when i trying to print output to div, strIlAd and strIlceAd print undefined.

Upvotes: 0

Views: 261

Answers (2)

Mike Brant
Mike Brant

Reputation: 71384

You should STRONGLY consider using deferred objects here to solve your problem. Let me give you an example for how you should work this based on jQuery's convenient when() method:

// This would be code in success handler for your outermost $.ajax() call.
// start "nested" ajax calls wrapped in when()
$.when(
    $.ajax({
        type: 'POST',
        url: '@Url.Action("IlAdGetir")',
        dataType: 'json',
        data: { id: ekranlar.il }
    }),
    $.ajax({
        type: 'POST',
        url: '@Url.Action("IlceAdGetir")',
        dataType: 'json',
        data: { id: ekranlar.ilce },
    })
).done(function(firstCall, secondCall) {
    // This is triggered when both calls are successful
    // set variables
    strIlAd = firstCall[0];
    strIlceAd = secondCall[0];
    divContent += '<label class="styledLabel">' +
    ' <img src=' + (ekranlar.resimURL).replace('~', '') +
    ' style="height:150px;width:150px;"/>' +
    '<input type="checkbox" id="' + ekranlar.ekranID + '" name="' + ekranlar.ekranAd + '" value="' + fiyat +
    '" class="styledCheck">' + '<br /><span>Ekran İsim: </span><span class="spanEkranAd">' + ekranlar.ekranAd +
    '</span><br /><span>' + 'Günlük Fiyat' + ': </span>' + fiyat + '<br /><span>Ekran Boyutu: </span><span class="spanEkranBoyut">'
    + ekranlar.ekranBoyutID + '"</span> <br/>' +
    '<span class="spanIl">' + strIlAd + '</span><br/> <span class="spanIlce">' + strIlAd + '</span> </label>';
    $("#imgDiv").append(divContent);
}).fail(function(){
    // your failure handler, triggered when either ajax call fails
});

You can see that this really consolidates your code, getting all success handling and failure handling for both ajax request in a single place.

Performance-wise and user-experience-wise, you will likely find this preferable to using synchronous ajax calls which will block the user's browser from doing anything else while you iterate through each record from outer ajax call and make two nested calls for each.

Upvotes: 1

Allende
Allende

Reputation: 1482

I already post my answer in comments anyway I can think in 2 ways to try solving your issue:

  1. Add async: false, to your nested calls
  2. Try moving your div print out to the last (the second one) nested "success" call, but first verify all the calls are being executed using debug tools (debug tools -> network).

Upvotes: 0

Related Questions