Jive Boogie
Jive Boogie

Reputation: 1265

How can I return a value from a function that uses a jQuery ajax call?

I have the following Javascript function that makes a call to an Asp.Net WebMethod that returns true if a username already exists and false if it does not. The following will give me the correct answer in an alert box but if I change the alert(result.d) to return result.d the result of the function is always undefined. How can I get the function that the Ajax call is contained in to return a value based on the response from the WebMethod?

function doesEnteredUserExist() {
        var valFromUsernameBox = $("#txtUserName").val();
        var jsonObj = '{username: "' + valFromUsernameBox + '"}'; 

        $.ajax({
        type: 'POST',
        contentType: 'application/json; charset=utf-8',
        data: jsonObj,
        dataType: 'json',
        async: false,
        url: 'AddNewUser.aspx/IsUserNameValid',
        success: function (result) {
            alert(result.d);
        },
        error: function (err) {
            alert(err);
        }
    });
}

Upvotes: 0

Views: 1496

Answers (8)

Fabrizio Calderan
Fabrizio Calderan

Reputation: 123417

This seems a good example of $.Deferred object usage

the idea is quite simple (really, I promise, :) see steps on the code)

  1. Create a new deferred object
  2. Make your ajax call. If result is false you will reject the deferred otherwise you will resolve it (you could reject it also on error ajax callback)
  3. return the promise
  4. Use .when() helper to check the status of the promise.

I create a fiddle which return randomically true or false in the response

function checkUserExist() {
    var dfd = $.Deferred();  /* step 1 */

    $.ajax({
        url: "/echo/json/",
        data: {
            "json": JSON.stringify({d: (Math.random() < 0.5) })
        },
        type: "POST",
        success: function (data) {
            console.log("result (inside ajax callback) ", data.d);
            if (!data.d) { dfd.reject() } else { dfd.resolve(); } /* step 2 */
        },
        error : ...
    });

    /* step 3 */         
    return dfd.promise();

}

$.when(checkUserExist())  /* step 4 */
    .fail(function() { console.log("user don't exist (inside fail)"); })
    .done(function() { console.log("user already exist (inside done)"); })

fiddle url : http://jsfiddle.net/Gh9cN/

(note: I've changed some internal details so to make it work on jsfiddle)

Upvotes: 0

timing
timing

Reputation: 6455

Ajax is asynchronous so once the function "doesEnteredUserExist" returns, the ajax call is not yet finished. Then later in the success callback you have the value. From there you should continue with your code and display the info to the user.

Upvotes: 1

Ghost-Man
Ghost-Man

Reputation: 2185

As @timing has mentioned, by the time the value is returned from thefunction, the ajax call is not complete so everytime you get the undefined.

This is not a solution to the problem, but an alternative method you can try for displaying it would be instead of returning the value, just update the innerHTML of some element like div with the returned text.Below is what I mean:

function doesEnteredUserExist() {
    var valFromUsernameBox = $("#txtUserName").val();
    var jsonObj = '{username: "' + valFromUsernameBox + '"}'; 

    $.ajax({
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    data: jsonObj,
    dataType: 'json',
    async: false,
    url: 'AddNewUser.aspx/IsUserNameValid',
    success: function (result) {
        //alert(result.d); 
       if(result.d==true){  //Just a check for the value whether true or 1 etc..
       $("#notifications").html('Username Already Exists'); // Have a div where you can display the message (named it notifications here) , update the notifications div text to notify the user
       }else{
          $("#notifications").html('Username is Available');
       }
    },
    error: function (err) {
        alert(err);
    }
});
}

Upvotes: 0

Jasper
Jasper

Reputation: 76003

Inside your success callback function if you return some value it doesn't set the return value for it's parent function. In this case the parent function is $.ajax and it always returns a jqXHR deferred object.

If you are using jQuery 1.5 or later the you can use deferreds. The idea is to save the jqXHR object returned from the AJAX request and wait for it to complete before returning it's value:

var jqXHR = $.ajax({...});

$.when(jqXHR).then(function (result) {
    return result.d
});

Docs for $.when(): http://api.jquery.com/deferred.when

An example of doing this would be to return the jqXHR object from your function and then wait for the AJAX request to resolve outside the function:

function doesEnteredUserExist() {
    return $.ajax({...});
}
$.when(doesEnteredUserExist).then(function (result) {
    //you can access result.d here
});

Upvotes: 0

Jeggs
Jeggs

Reputation: 250

I am guessing that you are trying to set result.d which is out of scope from the call which is why the alert (result.d) works as its in scope.

I may be getting the wrong end of the stick, you could use a global variable (not recommended), set that in the ajax return which you could then read from your function.

May need a bit more info or clarity on what your trying to achieve, as I read the question a couple of ways.

I normally do this (havent tested this):

function ajaxLoad(callback)
$.ajax({
        type: 'POST',
        async: true,
        url: 'url.aspx',
        data: d,
        cache: false,
        contentType: 'application/json',
        dataType: 'json',
        error: function (xmlHttpRequest, textStatus, errorThrown) {
    //error stuff
        },
        success: function (data) {
           if (typeof callback == 'function') { [callback(data)]; }
        }
    });

}

function callback(data)
{
    alert(data);
}

call the function using ajaxLoad('callback');

something like that!

Upvotes: 0

Jamie Hutber
Jamie Hutber

Reputation: 28106

Maybe give this a bash function onSucess (data) { alert(data.d); }

function doesEnteredUserExist() {
    var valFromUsernameBox = $("#txtUserName").val();
    var jsonObj = '{username: "' + valFromUsernameBox + '"}'; 

    $.ajax({
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    data: jsonObj,
    dataType: 'json',
    async: false,
    url: 'AddNewUser.aspx/IsUserNameValid',
    success: onSucess,
    error: function (err) {
        alert(err);
    }
});   
}

Upvotes: 0

wsanville
wsanville

Reputation: 37516

The thing to note is that the ajax function is non blocking. You specify two callback functions, one for success and one for error, one of these functions will get executed when the underlying request is finished.

Your doesEnteredUserExist does not wait for the ajax call to complete, and thus, the return value of the function is undefined.

The proper way to continue execution based on the result of your call is to break your functionality out into a separate function, and call that from your success function.

Upvotes: 2

blake305
blake305

Reputation: 2236

Store the value of result.d in a variable, then use it for whatever you would like.

Change this:

success: function (result) {
        alert(result.d);
    },

to this:

success: function (result) {
        var resultString = result.d;
    },

Now whenever you need result.d, just use the variable resultString. Basically, the ajax call is the only thing that can call the function that you wanted to return the value for, so you need to store that value when the function is called.

Upvotes: 0

Related Questions