0

I'm learning JavaScript by writing a Chrome extension for a website. The website has a section that displays a list of 4 videos, with a button to load more videos. When you click this button, it loads a new list of videos via an AJAX call.

I have a function, getNextVideo(), which gets the URL of the next video in the list. For example, if you are on the third video, then it'll grab the URL for the fourth video. If you're on the fourth video, then it'll simulate a click (which loads the new list of videos) via a function getNextVideoList() and then grab the first in the newly loaded list after a 1s timeout to wait for the DOM to update (I tried to use mutation observers but it was too complicated for my skill level).

function getNextVideo()
{
    if (getVideoPosition() == 4)
    {

        function ad()
        {
            getVideo(1);
        }

        setTimeout(ad, 1000);

        getNextVideoList();
    }
    else
    {
        var index = getVideoPosition() + 1;
        return getVideo(index);
    }
}

getVideoPosition() gets the index of the video in the list using some simple jQuery nth-child selectors. It returns the values 1, 2, 3, or 4.

getVideo(n) takes the index of the video (1, 2, 3, or 4) and returns the URL of that video. The returned value looks like this in the console: "http://video.example.com/video-id"

My problem is that when I run getNextVideo() on a video that is 4th in the queue, I get undefined returned in my console. How do I make the getNextVideo() function return the URL of the first video in the list after the AJAX call and subsequent DOM update?

lmike215
  • 115
  • 1
  • 6
  • can I see your Ajax call? You may need to wrap your callback in a proxy function – Paul Aug 22 '13 at 04:36
  • Looks like you have an off by one error. are you sure that the indexes you are using to iterate are in the range? especially in the getVideoPosition() and getVideo(n) ? – Hrishi Aug 22 '13 at 04:37
  • 2
    Read [Is it possible to return a value from `setTimeout`?](http://stackoverflow.com/questions/13730709/is-it-possible-to-return-a-value-from-settimeout-without-a-callback-function?rq=1) and [How to return a value from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call?rq=1) – DCoder Aug 22 '13 at 04:38

2 Answers2

1

This is because getNextVideo() doesn't have a return value when getVideoPosition() == 4. No return value shows up as undefined.

If you look at your code, there's no return inside the if (getVideoPosition() == 4) block. When there's no return from a function, the return value is undefined. If you want there to be a return value, then you have to add a return statement. Note, the function called by setTimeout() gets executed AFTER getNextVideo() has already returned so it can't participate in setting the return value.

If you really want to use asynchronous programming with setTimeout() (I'm not sure why you're doing that in the first place), then you will have to switch to an asynchronous programming model which means you won't use a return value from getNextVideo() at all, but will call a callback when it's done with the next value. That callback can be executed asynchronously from within the setTimeout(). But, I don't know why you're even using setTimeout() in the first place so I don't know if that extra complication is the best choice or not. If you got rid of the asynchronous setTimeout() then you could just return a value normally from that arm of getNextVideo() too.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thank you so much! I realized my code was very complicated and so I kept my code simple. What I did was put some code that set (I know, it's poor practice to write that code in a get method) a CSS class to the first video of the next list, waited a second, then got the URL. It all works perfectly. Thank you so much! – lmike215 Aug 22 '13 at 19:02
0

As far as my understanding to your code you are transferring control from your function "getNextVideo" to setTimeOut callback when condition occur.
Actual duty of your "getNextVideo" function is to "return getVideo(index);"

is it possible if you do your code like this.

        if (getVideoPosition() == 4)
{
    function ad()
    {
        getNextVideo(true);
    }
    setTimeout(ad, 1000);
    getNextVideoList();
}


function getNextVideo(isFirst)
{
    var index = isFirst==true?1:getVideoPosition() + 1;
    return getVideo(index);
}
Milan V.
  • 697
  • 1
  • 6
  • 22