Jammer
Jammer

Reputation: 2410

ajax loading 2 XML documents in order without async:false

I am loading 2 XML documents that both run functions on success, although the function for the 2nd XML document is dependant on the 1st being complete.

If I have async:true:

1st XML

function XmlDataTypes() {

    var result = null;
    var scriptUrl = "http://domain.com/xml/test.XmlDataTypes?AccountId=" + AccountId;
    $.ajax(
    {
        url: scriptUrl,
        type: 'get',
        dataType: 'xml',
        async: true,
        success: function (data) {

        //create array to be used in second XML
       for (var i = 0; i < xmlRows.length; i++) {

                        var dataType = xmlRows[i];

                        var dataTypeId = nodeValue(dataType.getElementsByTagName("DataTypeId")[0]);
                        var dataTypeName = nodeValue(dataType.getElementsByTagName("DataTypeName")[0]);

                        dataTypeArray.push({ dataTypeId: dataTypeId, dataTypeName: dataTypeName, position: i, markerArray: [] });

                    }



        },
        error: function onXmlError() {
            alert("An Error has occurred.");
        }

    });

    return result;

}

2nd XML

function XmlAmenityData() {

    var result = null;
    var scriptUrl = "http://domain.com/xml/test.XmlAmenityData?AccountId=" + AccountId;
    $.ajax(
    {
        url: scriptUrl,
        type: 'get',
        dataType: 'xml',
        async: true,
        success: function (data) {

        //store this info in markerArray in dataTypeArray

        },
        error: function onXmlError() {
            alert("An Error has occurred.");
        }

    });

    return result;

}

The XML data can loaded in a random order so the function for the second document will error if the 1st hasn't completed.

If I set:

async: false

It works correctly but I get a warning:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.

Is there a way around this without using:

async: false

Upvotes: 0

Views: 138

Answers (2)

Andre Mocke
Andre Mocke

Reputation: 86

You could try to return the $.ajax as a promise:

function XmlDataTypes() {

// note domain.com was changes to example.com - this should be changed back

var scriptUrl = "http://example.com/xml/test.XmlDataTypes?AccountId=" + AccountId;
return $.ajax(
{
    url: scriptUrl,
    type: 'get',
    dataType: 'xml',
    async: true,
    success: function (data) {

    //create array to be used in second XML
   for (var i = 0; i < xmlRows.length; i++) {

                    var dataType = xmlRows[i];

                    var dataTypeId = nodeValue(dataType.getElementsByTagName("DataTypeId")[0]);
                    var dataTypeName = nodeValue(dataType.getElementsByTagName("DataTypeName")[0]);

                    dataTypeArray.push({ dataTypeId: dataTypeId, dataTypeName: dataTypeName, position: i, markerArray: [] });

                }
    },
    error: function onXmlError() {
        alert("An Error has occurred.");
    }

});    

}

Then calling them in sequence :

XmlDataTypes.done(XmlAmenityData);

Here is some more documentation : http://www.htmlgoodies.com/beyond/javascript/making-promises-with-jquery-deferred.html

Upvotes: 0

John
John

Reputation: 91

Since the 2nd xml is dependent on the 1st, you can define a callback on success. Also since ajax is async, you must assign the result when the callback is called. You can define a variable ourside of your function (in this case an array) and put the data there.

var result = [];
function XmlDataTypes(url, accountId, callback) {
    var scriptUrl = url + accountId;
    $.ajax({
        url: scriptUrl,
        type: 'get',
        dataType: 'xml',
        async: true,
        success: function (data) {
             // do something
             result.push(data);
             if(typeof callback == 'function') {
                 callback();
             }
        },
        error: function onXmlError() {
            alert("An Error has occurred.");
        }
    });
}

function doSomething() {
    // Do something to store this info in markerArray in dataTypeArray
    // XmlAmenityData is in results var.
}

And you can use it like so

var _callback = XmlDataTypes("http://domain.com/xml/test.XmlAmenityData?AccountId=", "1234", doSomething);
XmlDataTypes("http://domain.com/xml/test.XmlDataTypes?AccountId=", "1234", _callback);

EDIT: Updated script based on given scenario.

Upvotes: 4

Related Questions