如何在第二个函数执行之前等待第一个函数完成执行?

时间:2016-04-01 20:17:08

标签: javascript jquery function youtube-api jquery-deferred

我试图想办法等到第一个函数(relatedVids(...))完成执行然后依次执行第二个函数(relatedVidsDetails())。代码所做的只是循环遍历来自youtube api的单个$.get(...)请求,并遍历其检索到的每个项目。

在调试器中测试的问题是,它将进入第一个函数(直到$.get()而实际上还没有得到任何东西)然后跳到第二个函数(再一次,直到$.get())。然后,它将继续执行第一个函数,直到它完成检索所有项目,然后当它进入第二个函数时,它将执行相同的操作,但出于某种神秘的原因,videoIdChainStr持有因为我怀疑它已经执行了第二个函数$.get(...)并且从未再次执行过第二次"第二次"所以第一个函数的字符串中的所有视频ID都从未被检索或执行过。当它有价值时。

所以,我的下一步是尝试使用$.Deferred(),据说这有助于在执行第二个函数之前首先解决第一个函数,因此它将保证第一个函数的值在第二个函数中使用没有跳过任何东西。但我不确定我是否正确行事,因为无论是否使用$.Deferred(),它仍然会做同样的事情。

第一个函数(relatedVids(...)):

var relatedVidsDefer = function relatedVids(videoId)
{
var r = $.Deferred();

$.get( // get related videos related to videoId
    "https://www.googleapis.com/youtube/v3/search",
    {
        part: 'snippet',
        maxResults: vidResults,
        relatedToVideoId: videoId,
        order: 'relevance',
        type: 'video',
        key: 'XXXXXXXXXX'
    },

    function(data)
    {
        debugger;
        $.each(data.items,
            function(i, item)
            {
                try
                {
                    console.log(item);
                    var vidTitle = item.snippet.title; // video title
                    var vidThumbUrl = item.snippet.thumbnails.default.url; // video thumbnail url
                    var channelTitle = item.snippet.channelTitle; // channel of uploaded video
                    var extractVideoId = null; // var to extract video id string from vidThumbUrl

                    // check if vidThumbUrl is not null, empty string, or undefined
                    if(vidThumbUrl)
                    {
                        var split = vidThumbUrl.split("/"); // split string when '/' seen
                        extractVideoId = split[4]; // retrieve the fourth index on the fourth '/'
                    }
                    else console.error("vidThumbUrl is either undefined or null or empty string.");
                    // if video title is longer than 25 characters, insert the three-dotted ellipse
                    if(vidTitle.length > 25)
                    {
                        var strNewVidTitle = vidTitle.substr(0, 25) + "...";
                        vidTitle = strNewVidTitle;
                    }

                    // check whether channelTitle is March of Dimes
                    if(channelTitle === "March of Dimes")
                    {
                        extractedVideoIdArr.push(extractVideoId); // add the extracted video id to the array

                        // check if extractedVideoIdArr is not empty
                        if(extractedVideoIdArr !== 'undefined' && extractedVideoIdArr.length > 0)
                        {
                            console.log("before join(): ", extractedVideoIdArr);
                            videoIdChainStr = extractedVideoIdArr.join(", "); // change from an array to a chain string of videoIds for the relatedVidsDetails() 
                            console.log("after join(): ", videoIdChainStr);
                        }

                        var vidThumbnail = '<div class="video-thumbnail"><a class="thumb-link" href="single-video.html"><div class="video-overlay"><img src="imgs/video-play-button.png"/></div><img src="' + vidThumbUrl + '" alt="No Image Available." style="width:204px;height:128px"/></a><p><a class="thumb-link" href="single-video.html">' + vidTitle + '</a><br/></div>'; //+ convert_time(vidDuration) + ' / Views: ' + viewCount + '</p></div>';

                        // print results
                        $('.thumb-related').append(vidThumbnail);
                        $(item).show(); // show current video thumbnail item 
                    }
                    else $(item).hide(); // hide current video thumbnail item
                }
                catch(err)
                {
                    console.error(err.message); // log error but continue operation    
                }
            } 
        ); 
    } 
);
return r;
};

第二个函数(relatedVidsDetails(...)):

var relatedVidsDetailsDefer = function relatedVidsDetails()
{
// change extractvideoid into a string by tostring() or join() for param to recognize
console.log("initial: ", extractedVideoIdArr);
$.get(
    "https://www.googleapis.com/youtube/v3/videos",
    {
        part: 'snippet, contentDetails, statistics',
        id: videoIdChainStr, // chain string of video ids to be called upon in a single request
        key: 'XXXXXXXXXX',
    },

    function(data)
    {
        debugger;
        $.each(data.items,
            function(i, item)
            {
                try
                {
                    console.log("relatedVidsDetails()", item);
                    console.log("extractedvideoidarr: ", extractedVideoIdArr[i]);
                    var _vidDuration = item.contentDetails.duration;
                    var _viewCount = item.statistics.viewCount;
                    console.log("id: " + extractedVideoIdArr[i] + " duration: " + _vidDuration);
                    console.log("id: " + extractedVideoIdArr[i] + " viewCount: " + _viewCount);


                }
                catch(err)
                {
                    console.error(err.message); // log error but continue operation    
                }
            }
        );
    }
);
};

第二次点击第二个功能时跳过代码:

$.each(data.items,
    function(i, item)
    {
       try
       {
           console.log("relatedVidsDetails()", item);
           console.log("extractedvideoidarr: ", extractedVideoIdArr[i]);
           var _vidDuration = item.contentDetails.duration;
           var _viewCount = item.statistics.viewCount;
           console.log("id: " + extractedVideoIdArr[i] + " duration: " + _vidDuration);
           console.log("id: " + extractedVideoIdArr[i] + " viewCount: " + _viewCount);
        }
        catch(err)
        {
           console.error(err.message); // log error but continue operation    
        }
     }
 );

由于第二个函数在videoIdChainStr为空时被逐步进入,然后在第一个函数完成时被跳过并且第二个函数准备就绪,因此跳过了代码。当它有值然后执行时,我无法得到videoIdChainStr

1 个答案:

答案 0 :(得分:0)

问题的答案是:“如何等待第一个函数在执行第二个函数之前完成执行”将是:

使用CALLBACK或PROMISES。

示例:

        function firstMethod() {
            // half of first method actions ...
            secondMethod(function() {
                // other half of first method actions
            });
        }

        function secondMethod(callBack) {
            // Second method actions
            setTimeout(function() { // The timeout is just a way to simulate the time that a response make us wait
                callBack();
            }, 5000);               
        }