views:

359

answers:

3

Hello Guys,

The function I called inside jquery returns undefined. I checked the function and it returns correct data when I firebugged it.

function addToPlaylist(component_type,add_to_pl_value,pl_list_no) 
    {
        add_to_pl_value_split = add_to_pl_value.split(":");

        $.ajax({
            type: "POST",
            url: "ds/index.php/playlist/check_folder",
            data: "component_type="+component_type+"&value="+add_to_pl_value_split[1],
            success: function(msg)
            {
                if(msg == 'not_folder')
                {
                    if(component_type == 'video')
                    {
                        rendered_item = render_list_item_video(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
                    }

                    else if(component_type == 'image')
                    {
                        rendered_item = render_list_item_image(add_to_pl_value_split[0],add_to_pl_value_split[1],pl_list_no)
                    }
                }
                else
                {
                    //List files from folder
                    folder_name = add_to_pl_value_split[1].replace(' ','-');

                    var x = msg; // json 
                    eval('var file='+x); 

                    var rendered_item;

                    for ( var i in file )
                    {
                        //console.log(file[i]);
                        if(component_type == 'video')
                        {
                            rendered_item = render_list_item_video(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
                        }

                        if(component_type == 'image')
                        {
                            rendered_item = render_list_item_image(folder_name+'-'+i,file[i],pl_list_no) + rendered_item;
                        }
                    }
                }

                $("#files").html(filebrowser_list); //Reload Playlist

                console.log(rendered_item);

                return rendered_item;
            },
            error: function()
            {
                alert("An error occured while updating. Try again in a while");
            }
         })         
    }

$('document').ready(function()
{
    addToPlaylist($('#component_type').val(),ui_item,0); //This one returns undefined
});
+4  A: 

The function addToPlaylist doesn't return anything. It makes an asynchronous request, which eventually executes a callback function, which returns something. The original addToPlaylist function is long done and returned by the time this happens though, and the callback function returns to nobody.

I.e. the success: function(msg) { } code executes in a different context and at a later time than the surrounding addToPlaylist function.

Try this to see it in action:

function addToPlaylist() {
    $.ajax({
        ...
        success : function () {
            alert('second');  // comes after 'first'
            return null;      // returns to nobody in particular
        }
    });
    alert('first');      // comes before 'second'
    return 'something';  // can only return here to caller
}
deceze
+1  A: 

I agree with deceze. What you need to do is perform the necessary action(s) for rendered_item in the success function rather than relying on getting something back from addToPlayList().

ChrisP
+1  A: 

You're making your request via AJAX, which by definition is asynchronous. That means you're returning from the function before the AJAX request completes. In fact, your return statement is meaningless as it returns from the callback function, not your addToPlaylist function.

You have a couple of choices. The first one is better.

First, you can work with the asynchronous nature of the AJAX request and pass a callback into your addToPlaylist method (much like you're passing in the anonymous callback to the ajax function) and have the AJAX callback, call that function instead of doing the return. That way your request completes asynchronously and doesn't lock up your browser while it's going on.

function addToPlaylist(component_type, add_to_pl_value, pl_list_no, cb )
{
    ...yada yada yada...
    $.ajax({
         ...
         success: function(data) {
            ...
            if (cb) {
               cb.apply(this, rendered_item );
            }
         }
    });
}

Second, you can add the option aSync: false to the ajax call. This will force the AJAX call to run synchronously (essentially it just loops until the call returns then calls your callback). If you do that, you need to capture a local variable in your addToPlaylist function inside the callback and assign the value(s) to it from the callback. At the end of the addToPlaylist function, return this variable as the result.

function addToPlaylist(component_type, add_to_pl_value, pl_list_no )
{
    ...yada yada yada...
    var result = null;
    $.ajax({
         aSync: false,
         ...
         success: function(data) {
            ...
            result = rendered_item;
         }
    });

    return rendered_item;
}
tvanfosson
Thanks deceze and tvanfosson! now I understand it. But how will I call the ajax callback on your first method?
steamboy
The callback is `cb`. I've shown it invoked using `apply`.
tvanfosson
I did this addToPlaylist($('#component_type').val(),ui_item,0,cb); but still returns undefinded. I'm not sure how to do it. Appreciate your help a lot.
steamboy
If you use the callback, you shouldn't expect the function to return anything -- you should put the code that uses the value obtained by the AJAX call into the callback function.
tvanfosson