Проблемы с contentDetails, длительностью и статистикой из Youtube API v3

Я пытаюсь получить значения для duration и viewCount для каждого видео, оба в разделе video:list api. Я создал отдельную функцию, которая будет возвращать продолжительность каждого видео и статистику. Единственное, что работает, — это список воспроизведения видео, которые были получены и videoId в рамках функции getPlaylist(...). Зашел в консоль и вот что получаю:

console.log("id: " + videoId + " duration: " + vidDuration + " viewCount: " + viewCount); // return value in console

id: xxx duration: undefined viewCount: undefined

У меня никогда не работала продолжительность, но я заметил, что API с part: statistics извлекает значение общей суммы просмотров из каналов, где они закомментированы. Но это не то, что я ищу. Я хочу, чтобы он работал с каждым видео, используя:

GET https://www.googleapis.com/youtube/v3/videos

Но по какой-то причине я не могу заставить его работать. У меня есть свойство videoId в качестве параметра, поэтому playlistId может прочитать его и получить указанное значение для продолжительности видео и количества просмотров, но оно по-прежнему остается неопределенным, даже когда videoId было определено. О, и диалоговое окно предупреждения тоже не появляется.

Что мне здесь не хватает?

Сценарий:

var channelName = 'ExampleChannel';
var vidWidth = 500;
var vidHeight = 400; 
var vidResults = 15; /* # of videos to show at once - max 50 */
var vidDuration = "";
var viewCount = 0;
var videoId = "";

$(document).ready(function() {
    $.get( // get channel name and load data
        "https://www.googleapis.com/youtube/v3/channels",
        {
            part: 'contentDetails',
            forUsername: channelName,
            key: 'XXXXXXXXXX'
        },

        function(data)
        {
            $.each(data.items, 
                function(i, item) {
                    console.log(item); // log all items to console
                    var playlistId = item.contentDetails.relatedPlaylists.uploads;
                    //var viewCount = console.log(item.statistics.viewCount);
                    getPlaylists(playlistId);

            })
        }         
    );

    // function that gets the playlists
    function getPlaylists(playlistId)
    {
        $.get(
            "https://www.googleapis.com/youtube/v3/playlistItems",
            {
                part: 'snippet',
                maxResults: vidResults,
                playlistId: playlistId,
                key: 'XXXXXXXXXX'
            },

            // print the results
            function(data)
            {
                var output;
                $.each(data.items, 
                    function(i, item) {
                        console.log(item);
                        var vidTitle = item.snippet.title; // video title
                        var vidDesc = item.snippet.description; // video description
                        var videoId = item.snippet.resourceId.videoId; // video id

                        // check if description is empty
                        if(vidDesc == null || vidDesc == "")
                        {
                            vidDesc = "No description was written."; // FIX: test msg to see where it still shows up
                            $('#desc').remove(); // remove video description
                        }
                        else vidDesc = item.snippet.description;

                        vidDuration = getVideoDuration(videoId);
                        viewCount = getViewCount(videoId);
                        console.log("id: " + videoId + " duration: " + vidDuration + " viewCount: " + viewCount); // return value in console

                        output = '<li><iframe height="' + vidHeight + '" width="' + vidWidth + '" src=\"//www.youtube.com/embed/' + videoId + '\"></iframe></li><div id="title">' + vidTitle + '</div><div id="desc">' + vidDesc + '</div><div id="duration">Length: ' + vidDuration + '</div><div id="stats">View Count: ' + viewCount + '</div>';

                    // Append results to list tag
                    $('#results').append(output);
                })
            }         
        );
    }

    // return video duration
    function getVideoDuration(videoId) 
    { 
        $.get(
            "https://www.googleapis.com/youtube/v3/videos",
            {
                part: 'contentDetails',
                id: videoId,
                key: 'XXXXXXXXXX',
            },

            function(data)
            {
                $.each(data.items,
                    function(i, item) {
                        //videoId = item.snippet.resourceId.videoId;

                        alert(item.contentDetails.duration); // video duration
                        //alert(videoId);
                    })    
            }
        );
    }

    // return video view count
    function getViewCount(videoId) 
    { 
        $.get(
            "https://www.googleapis.com/youtube/v3/videos",
            {
                part: 'contentDetails, statistics',
                id: videoId,
                key: 'XXXXXXXXXX',
            },

            function(data)
            {
                $.each(data.items,
                    function(i, item) {
                        //videoId = item.snippet.resourceId.videoId;

                        alert(item.statistics.viewCount); // view count
                        //alert(videoId);
                    })  
            }
        );
    } 
});

Скриншот: (обновление)

введите здесь описание изображения


person TheAmazingKnight    schedule 19.02.2016    source источник


Ответы (1)


Потому что, когда вы вызываете эти функции, вы не ждете завершения функции. Вам нужно использовать Promise в Javascript.

Я немного изменяю ваш код (проверено с моим ключом API)

var channelName = 'example';
var vidWidth = 500;
var vidHeight = 400; 
var vidResults = 15; /* # of videos to show at once - max 50 */
var vidDuration = "";
var viewCount = 0;
var videoId = "";

$(document).ready(function() {
    $.get( // get channel name and load data
        "https://www.googleapis.com/youtube/v3/channels",
        {
            part: 'contentDetails',
            forUsername: channelName,
            key: 'xxx'
        },

        function(data)
        {
            $.each(data.items, 
                function(i, item) {
                    //console.log(item); // log all items to console
                    var playlistId = item.contentDetails.relatedPlaylists.uploads;
                    //var viewCount = console.log(item.statistics.viewCount);
                    getPlaylists(playlistId);

            });
        }         
    );

    // function that gets the playlists
    function getPlaylists(playlistId)
    {
        $.get(
            "https://www.googleapis.com/youtube/v3/playlistItems",
            {
                part: 'snippet',
                maxResults: vidResults,
                playlistId: playlistId,
                key: 'xxx'
            },

            // print the results
            function(data)
            {
                var output;
                $.each(data.items, 
                    function(i, item) {
                        console.log(item);
                        var vidTitle = item.snippet.title; // video title
                        var vidDesc = item.snippet.description; // video description
                        var videoId = item.snippet.resourceId.videoId; // video id

                        // check if description is empty
                        if(vidDesc == null || vidDesc == "")
                        {
                            vidDesc = "No description was written."; // FIX: test msg to see where it still shows up
                            $('#desc').remove(); // remove video description
                        }
                        else vidDesc = item.snippet.description;

                        getVideoDuration(videoId).done(function(d, v){
                             vidDuration = d;
                             //console.log(r);

                      
                               viewCount = v;

                        document.write("id: " + videoId + " duration: " + vidDuration + " viewCount: " + viewCount); // return value in console
                                
                        document.write("<br>");

                        output = '<li><iframe height="' + vidHeight + '" width="' + vidWidth + '" src=\"//www.youtube.com/embed/' + videoId + '\"></iframe></li><div id="title">' + vidTitle + '</div><div id="desc">' + vidDesc + '</div><div id="duration">Length: ' + vidDuration + '</div><div id="stats">View Count: ' + viewCount + '</div>';

                    // Append results to list tag
                    $('#results').append(output);
                   });
                });
            }         
        );
    }

    // return video duration
    function getVideoDuration(videoId) 
    { 
        var dfrd1 = $.Deferred();
        var r = '';
        $.get(
            "https://www.googleapis.com/youtube/v3/videos",
            {
                part: 'contentDetails',
                id: videoId,
                key: 'xxx',
            },

            function(data)
            {
                $.each(data.items,
                    function(i, item) {
                        //videoId = item.snippet.resourceId.videoId;
                        var view = 0;
                        r = item.contentDetails.duration; // video duration 
                        getViewCount(videoId).done(function(t){
                          view = t;
                          dfrd1.resolve(r, view);
                        });
                        
                        //alert(videoId);
                    });    
            }
        );
        return dfrd1.promise();
    }

    // return video view count
    function getViewCount(videoId) 
    { 
        var dfrd2 = $.Deferred();
        var r = '';
        $.get(
            "https://www.googleapis.com/youtube/v3/videos",
            {
                part: 'contentDetails, statistics',
                id: videoId,
                key: 'xxx',
            },

            function(data)
            {

                $.each(data.items,
                    function(i, item) {
                        //videoId = item.snippet.resourceId.videoId;

                        r = item.statistics.viewCount; // view count
                        //alert(videoId);
                        dfrd2.resolve(r);

                      // console.log("in", r);
                    });  
            }
        );
        return dfrd2.promise();
    } 
});

изменить

Другими словами, это вызов асинхронного метода.

getVideoDuration(videoId).done(function(r)

Пояснение:

Вызов функции getVideoDuration и .done говорит о том, что функция getVideoDuration вернет результат, когда мы разрешим обещание (dfrd1.resolve(r);). Тем временем функция return dfrd1.promise(); означает, что результат будет отложен. Когда обещание будет разрешено, мы входим в done и можем сделать все остальное :)

То, что вы видите на скриншоте, логично, потому что есть два Promise ! Моя ошибка, я не увидел повторяющуюся строку ввода. Я изменяю код, чтобы решить эту проблему.

Таким образом, сначала будет разрешена функция getVideoDuration, а затем вторая. Когда разрешается вторая функция, мы разрешаем первое обещание отправить результат функции getPlaylists(playlistId)

ИЗМЕНИТЬ 25 февраля

я меняю код в связи с ошибкой с промисами.

person mpgn    schedule 19.02.2016
comment
Большое спасибо за помощь! Я хотел бы понять, что вы здесь сделали и почему это сработало так, как вы это сделали? Я никогда раньше не использовал методы Promise или Deferred и даже не слышал о них! Я всегда думал, что вы знаете, если вы вызвали параметризованный метод, он пройдет через него и вернет значение. Я заметил, что в консоли сначала возвращаются все объекты, а затем все отдельные значения продолжительности и количества просмотров. Не могли бы вы уточнить? Заранее спасибо! - person TheAmazingKnight; 19.02.2016
comment
Еще один вопрос, пытаюсь разобраться. Я заметил, что сразу после печати всей разной продолжительности на консоль выводится последнее повторяющееся значение одинаковой продолжительности. Пост обновлен! - person TheAmazingKnight; 20.02.2016