tags:

views:

46

answers:

3

I'm getting undefined for some reason when I try to return the html via the callback function:

function getDataFromUrl(urlWithContent)
{  
    // jQuery async request
    $.ajax(
    {
        url: urlWithContent,
        dataType: "html",
        success: function(data) {
                                    return $('.result').html(data);
                                },
        error: function(e) 
        {
            alert('Error: ' + e);
        }
    });
}

I know I'm getting data back, I see it in firebug in the response and also when I alert out the data, I see the entire page content come up in the alert box.

When I call my function, I am doing the following:

var divContent = getDataFromUrl(dialogDiv.attr("href"));

if(divContent)
    dialogDiv.innerHTML = divContent;

when I alert out the divContent (before the if statement) I'm getting undefined. Maybe I'm just going about this wrong on how I'm returning back the data?

I also tried just return data; same thing, I get undefined after the call to this method when set to my variable.

Updated per responses:

Tried this, still getting undefined:

function getDataFromUrl(urlWithContent, divToUpdate)
{  
    $.ajax(
    {
        url: urlWithContent,
        aSync: false,
        dataType: "html",
        success: function(data) {
                                    divToUpdate.innerHTML = data;
                                },
        error: function(e) 
        {
            alert('Error: ' + e);
        }
    });
}

I called it from within another function like this:

var divContent = "";

if (dialogDiv.attr("href"))
{
    getDataFromUrl(dialogDiv.attr("href"), divContent);
}
+3  A: 

The ajax call runs asynchronously. Therefore your function returns (by dropping out of the end of the block) before your ajax call completes. You have two ways to handle this. Add the aSync: false option to force the ajax call to run synchronously or use a callback to your function that can be executed when the ajax call completes. I'd prefer the latter.

function setDataFromUrl(urlWithContent,callback) 
{   
    // jQuery async request 
    $.ajax( 
    { 
        url: urlWithContent, 
        dataType: "html", 
        success: function(data) { 
                                    callback(data);
                                }, 
        error: function(e)  
        { 
            alert('Error: ' + e); 
        } 
    }); 
}

setDataFromUrl(dialogAnchor.attr("href"), function(data) {
     dialogDiv.html(data);
});

or even better, unless you're sharing this code in lots of places:

var dialogDiv = $('div.dialog');
var dialogAnchor = dialogDiv.find('a');
// jQuery async request 
$.ajax( 
{ 
    url: dialogAnchor.attr('href'), 
    dataType: "html", 
    success: function(data) { 
                                dialogDiv.html(data);
                            }, 
    error: function(e)  
    { 
        alert('Error: ' + e); 
    } 
});
tvanfosson
When you say runs async, at the same time...at the same time as what, the DOM loading?
CoffeeAddict
Here's a great analogy for synch v/s async calls - http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/faca1575f306ba0f?pli=1. The code samples are from GWT, but the idea is applicable here as well.
sri
@coffeeaddict -- when you call the ajax method, it actually returns before the call is complete, meaning that the next line of code (here the end of the block) may execute before the actual request is completed. It doesn't wait until the request completes before continuing to the next line in your function. If you set `async` to false, then it will wait, but you still have a problem: namely that the return is actually returning from the ajax completion callback, not your function. You'd need to capture the value in locally-scoped variable, then return it at the end of your function.
tvanfosson
@sri: that is a BRILLIANT analogy.
Andy Shellam
we are sharing/reusing this code in a lot of places
CoffeeAddict
dialogDiv resides in another function that is calling this async function
CoffeeAddict
isn't this what I essentially did: divToUpdate.innerHTML = data;
CoffeeAddict
+3  A: 

You cannot return data from the callback - because there's no guarantee that the data will have been returned back from the function at the time the function exits (as it's an asynchronous call.)

What you have to do is update the content within the callback, like:

success: function(data) {
    $('#dialogDiv').html(data);
},

where your dialog DIV has id="dialogDiv" attached to it.

I think you can also modify your function to take the object to update when the call completes like so:

function getDataFromUrl(urlWithContent, divToUpdate)
{  
    // jQuery async request
    $.ajax(
    {
        url: urlWithContent,
        dataType: "html",
        success: function(data) {
            divToUpdate.innerHTML = data;
        },
        error: function(e) 
        {
            alert('Error: ' + e);
        }
    });
}

Then call it like so (where dialogDiv is the object representing the DIV to update like in your example.)

getDataFromUrl(dialogDiv.attr("href"), dialogDiv);
Andy Shellam
"because there's no guarantee that the data will have been returned back from the function at the time the function exits" but if I'm doing this in the success, doesn't that right there tell me there is data?
CoffeeAddict
No, because that function isn't executed until the data is returned from the AJAX call, which could be **after** your `getDataFromUrl` function exits, depending on the client's connection speed to the remote server. What you're doing is firing off the AJAX request, saying "let me know when it comes back" then carrying on with what you were doing before - i.e. exiting from the `getDataFromUrl` function.
Andy Shellam
Thanks your example really helped me gain a better perspective (way to approach this)
CoffeeAddict
weird, I thought that if I call getDataFromUrl, that it won't exit the function until success...which means it has data..
CoffeeAddict
No - that's the idea of it being asynchronous - it's processed without halting the function execution. If it was a synchronous call, then yes, the function would wait until the data has been returned before exiting from `getDataFromUrl` but you would still need to store the data in a local variable, not just return it from the callback. Any how, synchronous AJAX calls are **BAD**!
Andy Shellam
so what is processed without halting, the request? and then the success is checked when?
CoffeeAddict
The rest of the function. The execution stack could look like this: 1. You call getDataFromUrl. 2. getDataFromUrl makes AJAX request. 3. getDataFromUrl exits (while AJAX request runs in background) 4. AJAX request completes and your success function executes. See the problem? If your connection is fast enough, #4 could happen before #3 - the order is not guaranteed. If the request is successful, your success function executes. If not, your error function executes.
Andy Shellam
Kudos to @sri for this wonderful analogy of asynchronous programming - please read it, it should help you understand better what's going on. http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/faca1575f306ba0f?pli=1
Andy Shellam
yea, just read it....and I guess I'm still lost here in terms of the waiting (callback). I essentially gave it a callback using a function in the success didn't I?
CoffeeAddict
so you're saying getDataFromUrl will exit, meaning after it makes the ajax call, the function exits...ok. So then if I've defined a function in success: then you're saying that's going to be executed whenever the response gets back? Ok, so if I'm in my "other" function that originally called getDataFromUrl, then how does it know when the passed variable divToUpdate has the data?
CoffeeAddict
Sorry, I'm very new to all this...haven't done much async programming and yes that thread is also good, but I'm still missing something here.
CoffeeAddict
Your success function **is** the callback. A callback is a function that gets "called" when something happens - in this case, when the AJAX request completes successfully. You cannot return anything from a callback, you can only take whatever action you need to **within the callback** - which is what the example in my answer is doing. P.S. did you see my comment to your update in the question?
Andy Shellam
You're correct with your previous statements about the function making the request and exiting before the response came back etc. Your callback function is updating the content within divToUpdate - when this happens it tells the browser to render the updated content. The whole point of async programming is you don't wait for something to come back, you take action **when** it does, allowing the user to carry on interacting with the rest of the application while the async request completes in the background.
Andy Shellam
"Your success function is the callback. A callback is a function that gets "called" when something happens - in this case, when the AJAX request completes successfully". Right, I get that totally even before posting this thread. I did set the passed divToUpdate in that callback function. So I don't get why it's undefined still when I put an alert(divToUpdate); right after my call to getDataFromUrl
CoffeeAddict
oh god. Per Andy's last post, I was passing in the wrong damn variable divContent. My fault.
CoffeeAddict
I appreciate everyone's time. I think my main problem was that I thought I could return something from a callback...and then looking at it as passing in the object to be set rather than trying to set it via a var in the first function.
CoffeeAddict
A: 

Why dont you try this:

function getDataFromUrl(urlWithContent)
{  
    // jQuery async request
    $.ajax(
    {
        url: urlWithContent,
        dataType: "html",
        success: function(data) {
                                    $('#dialogDiv').html(data);
                                },
        error: function(e) 
        {
            alert('Error: ' + e);
        }
    });
}

And just call the function and not assign it to any variable.

HTH

Raja
what do you mean? the dialogDiv is a variable (or incoming param) to another function that calls this one. How would it know about the other variable or param?
CoffeeAddict
If it is dynamic then you might have to follow Andy's method since it makes a lot of sense.
Raja