• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 679
  • Last Modified:

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?
0
flynny
Asked:
flynny
3 Solutions
 
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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
 
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

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now