Ajax Return Issue

Hi all,

I am trying to return values from an ajax return but am having difficulty, I assume I am missing something regarding the .promise or async of the method.

function addFontField(element) {
    var fonts = runAjax('/Public/AdminServices.asmx/GetFonts', null);
    alert("fonts" + fonts); //is alerting undefined

}

function getFonts() {

    runAjax('/Public/AdminServices.asmx/GetFonts', null)
        .done(
            function (__exists) {

                if (__exists.d) {
                    alert(__exists.d); // alerts the [Object object, Object object] array as expected
                    return __exists.d;
                }
                else {
                   alert(__exists.d);
                   return false;
                }
            }
        )
        .fail(
            function (jqXHR, textStatus, errorThrown) {
              alert(errorThrown + ':' + textStatus + ':' + jqXHR.responseText);
              return false;
            }
        );

}

function runAjax(webmethod, fields) {

    //stringify passed field array
    if (fields !== null) {
        var jsonObject = {};

        for (var i = 0; i < fields.length; i++) {
            jsonObject[fields[i].fieldname] = fields[i].fieldtext;
        }

        return $.ajax({
            type: "POST",
            url: webmethod,
            data: JSON.stringify(jsonObject),
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    }
    else {
        return $.ajax({
            type: "POST",
            url: webmethod,
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    }  
}

Open in new window


Now I am returning a List<KeyValuePair<String, String>> from my c# function. It appears to be getting to the .success method, but when i return it to the var in getfonts() it is undefined at this point?
flynnyAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

guru_samiCommented:
I think your  alert("fonts" + fonts) is executed even before the ajax call is finished.
You can test it by setting changing your async call to sync.

pass async:false to your .ajax method.

If you get the values with above setting, it means you will have to rethink your code flow...
0
flynnyAuthor Commented:
Hi guru.

I did try adding this (although I would rather not set async false) but got the same behaviour. Do I not cover for this with my runajax method? As u thought I was implementing a promise with this code
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
I'm a bit confused here... On line 2 of your code above, you are calling your "runAjax" method but should this really be your "getFonts" method?

However, the strange thing is, that even though the return value of runAjax should be JQuery's "jqXHR" object (ie. it's not going to be your "font") that definitly should not be return an "undefined" value.

My guess is that you have changed the code... When you originally were calling the getFonts() method, that's when you were getting the "undefined" return value and then since then you were trying things and changed that from calling getFonts() to calling runAjax(...) directly. So can you confirm that the code EXACTLY as above does not have "undefined" in the alert.

BTW, the "undefined" return value from getFonts() is correct because in your getFonts() method you never actually return anything. The "return" statements that you see in there, are actually just returning from the done/fail callback functions. To do what you want, because of the async nature, you need to use your own callbacks, ie. something like this... (with a bit more error checking, etc, I'm just trying to give you the idea)
function addFontField(element) {
    getFonts(function(result) {
        alert("fonts" + result); // should 'alert' what you are after
        // Do something usefult with 'result'
    });
}

function getFonts(callback) {

    runAjax('/Public/AdminServices.asmx/GetFonts', null)
        .done(
            function (__exists) {

                if (__exists.d) {
                    alert(__exists.d); // alerts the [Object object, Object object] array as expected
                    callback(__exists.d);
                }
                else {
                   alert(__exists.d);
                   callback(false);
                }
            }
        )
        .fail(
            function (jqXHR, textStatus, errorThrown) {
              alert(errorThrown + ':' + textStatus + ':' + jqXHR.responseText);
              callback(false);
            }
        );

}

function runAjax(webmethod, fields) {

    //stringify passed field array
    if (fields !== null) {
        var jsonObject = {};

        for (var i = 0; i < fields.length; i++) {
            jsonObject[fields[i].fieldname] = fields[i].fieldtext;
        }

        return $.ajax({
            type: "POST",
            url: webmethod,
            data: JSON.stringify(jsonObject),
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    }
    else {
        return $.ajax({
            type: "POST",
            url: webmethod,
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    }  
}

Open in new window

0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

Miguel OzSoftware EngineerCommented:
$.ajax and runAjax returns nothing, because all ajax calls are asynchronous by default, thus will the reason "fonts" variable is undefined.
A possible solution: Assign fonts in the done/success call back and execute your page logic afterwards. (This is the typical JS AJAX results interaction  and you can see it in any examples of knockout or angular)

Note: You may want to use setting async = false but it is not recommended as per jquery ajax help:
async (default: true)
Type: Boolean
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().
0
RobOwner (Aidellio)Commented:
You just need to chain your ajax with the done event:

function addFontField(element) {
    runAjax('/Public/AdminServices.asmx/GetFonts', null).done(function(data) {
    alert("fonts" + data); //is alerting undefined
});

}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
flynnyAuthor Commented:
Hi all,

thanks for the help. I have the following code;

function addFontField(element) {

    runAjax('/Public/AdminServices.asmx/GetFonts', null)
    .done(function (fonts) {
        alert(fonts);
        alert(Object.keys(fonts).length);

        var html = "<ul class='fontList'>";

        for(var i=0; i<fonts.length; i++)
        {
            html += "<li data-url='" + fonts[0][0] + "'>" + fonts[0][1] + "</li>";
        }

        html += "</ul>";
    });
}

Open in new window


now the first alert is returning Object object and the second alert is giving 1? From testing server side I am sending back

List<KeyValuePair<String, String>>

with 2 rows in it? Do I need to convert the return to an array?
0
flynnyAuthor Commented:
Ok,

after googling I apologise i access the .d for return data;

However, I am facing a further issue. How do I access the string in the array as

        for(var i=0; i<fonts.d.length; i++)
        {
            html += "<li data-url='" + fonts.d[i][0] + "'>" + fonts.d[i][1] + "</li>";
        }

Open in new window


is returning undefined for both elements?
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Try this...
        for(var i=0; i<fonts.d.length; i++)
        {
            html += "<li data-url='" + fonts.d[i]['Key'] + "'>" + fonts.d[i]['Value'] + "</li>";
        }

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
jQuery

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.