0

I am definitely not seeing this straight so am looking for a quick hand. I've been googling about and not found much that has helped.

Set the scene:

I have a node app that uses the 'googleapis' package. Now, I have that working fine and returning data (mostly) as expected.

The problem comes when I have to make a separate call to get the duration for each video (only way to get that bit of data is with a separate call).

I don't seem to be able to pass the duration value up the scope. I know I'm not doing it right and need to do it different but I just can't see the wood for the trees here.

youtubeClient.search.list({ part: 'id,snippet', maxResults: 10, q: searchTerm, type: 'video' }, 
        function (err, data) {
            if (err) {
                console.error('Error: ' + err);
            }

            if (data) {
                var returnList = [];

                for (var item in data.items) {

                    var duration = '00:00'; // THIS IS THE VARIABLE I WANT POPULATED
                    var value = data.items[item].id.videoId;

                    youtubeClient.videos.list({ part: 'contentDetails', id: data.items[item].id.videoId }, 
                        function (err, details) {
                            if (err) {
                                console.error('Error: ' + err);
                            }

                            if (details) {
                                // THIS IS WHERE I AM TRYING TO SET THE DURATION FIELD FROM THE RESULT
                                duration = details.items[0].contentDetails.duration;
                            }
                    });

                    returnList.push({value: value, duration: duration});

                }

                res.json(returnList);
            }
        });

As you can see, what I am trying to achieve shouldn't be at all difficult so any help would be appreciated. Thank you.

6
  • 1
    This is a classic async operation inside a loop problem. The loop runs to completion before even the first async operation finishes and calls its callback, messing up the timing of everything. Suggest you do some searches to understand more about why your code doesn't work. Unfortunately, I don't think there's a good canonical answer that can be used as a reference for all of these types of questions. Commented May 30, 2016 at 2:03
  • 1
    npmjs.com/package/async Commented May 30, 2016 at 2:04
  • I had a feeling that would be exactly the case jfriend00. that is a shame, I will look in to it a bit more Commented May 30, 2016 at 2:09
  • You can start here:How to return value from asynchronous call. Commented May 30, 2016 at 2:46
  • And, also this one from earlier today: For loop in redis with nodejs asynchronous requests and program fails because readFile is asynchronous? Commented May 30, 2016 at 2:49

1 Answer 1

0

I managed to resolve my issue with the help of the following stack question; Calling an asynchronous function within a for loop in JavaScript

Basically I had to refactor a little to get it in the anonymous function but it worked a treat....

youtubeClient.search.list({ part: 'id,snippet', maxResults: 10, q: searchTerm, type: 'video' }, 
    function (err, data) {
        if (err) {
            console.error('Error: ' + err);
        }

        if (data) {
            var returnList = [];

            var total = data.items.length;
            var count = 0;

            for(var i = 0; i < total; i++){
                var returnItem = {};

                (function(foo){
                    returnItem = {
                        duration: '00:00',
                        value: data.items[foo].id.videoId
                    };

                    youtubeClient.videos.list({ part: 'contentDetails', id: returnItem.value }, 
                        function (err, details) {
                            if (err) {
                                console.error('Error: ' + err);
                            }

                            if (details) {
                                returnItem.duration = details.items[0].contentDetails.duration;

                                returnList.push(returnItem);
                            }

                            count++;
                            if (count > total - 1) {
                                // I CAN EXIT FROM HERE NOW
                            }
                    });

                }(i));
            }
        }
    });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.