问题
I'm having a problem with the asynchronous methods that prints and returns all vidDuration
values then viewCount
values were placed for each videoId, but vidDuration
repeated only the last value that was received and assigned it to all of the videoId
s which is clearly wrong.
I tried setting up a temporary array called tempArray
within the loop that store each of the vidDuration
values which it did, then to print them to each vidDuration
, but then again, it looped through the output however many values are in the array and duplicated the videos, which I don't want. I commented out lines involving tempArray
and reverted back to the working problem.
From what I understand, the async methods printed all of the duration values without going to the output as if it got stuck there until it was done and resolved and then it looped the viewCount
and output perfectly fine. I'm wondering how do I fix this in a programmatically logical way?
Script:
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: 'XXXXXXXX'
},
function(data)
{
$.each(data.items,
function(i, item) {
console.log(item); // log all items to console
var playlistId = item.contentDetails.relatedPlaylists.uploads;
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: 'XXXXXXXX'
},
// print the results
function(data)
{
var output;
/*var tempArray = new Array();*/ // temporary array for storing video duration values
$.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(r){
vidDuration = r;
console.log(r);
/*tempArray[i] = r;*/ // store value into each array index
/*console.log("Array:", tempArray[i], tempArray);*/ // log to console
/*i++;*/ // increment
getViewCount(videoId).done(function(r){
viewCount = r;
console.log(r);
//vidDuration = getVideoDuration(videoId);
//viewCount = getViewCount(videoId);
// temp array index to loop thru array
/*$.each(tempArray, function(i){
vidDuration = tempArray[i]; // assign index value to vidDuration
console.log("In Each vidDuration: ", vidDuration);
i++;
});*/
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);
}); // end of getVideoDuration(videoId).done
}); // end of getViewCount(videoId).done
});
/*console.log("TEMPARRAY[]",tempArray);*/ // print entire array
}
);
}
// return video duration
function getVideoDuration(videoId)
{
var defer1 = $.Deferred();
var r = '';
$.get(
"https://www.googleapis.com/youtube/v3/videos",
{
part: 'contentDetails',
id: videoId,
key: 'XXXXXXXX',
},
function(data)
{
$.each(data.items,
function(i, item) {
r = item.contentDetails.duration;
defer1.resolve(r);
console.log("in vidDuration func", r);
});
}
);
return defer1.promise();
}
// return video view count
function getViewCount(videoId)
{
var defer2 = $.Deferred();
var r = '';
$.get(
"https://www.googleapis.com/youtube/v3/videos",
{
part: 'contentDetails, statistics',
id: videoId,
key: 'XXXXXXXX',
},
function(data)
{
$.each(data.items,
function(i, item) {
r = item.statistics.viewCount;
defer2.resolve(r);
console.log("in viewCount func", r);
});
}
);
return defer2.promise();
}
});
Screenshot results (normal refresh):
Screenshot results (using debugger):
Here's a screenshot of the results when stepping through with the debugger console. (Why are the results different from when the page normally loads? Is this typical action of the async methods? How do I fix this?)
回答1:
In fact the second promise is misplaced, the second promise is resolved AFTER that all the promises from the first promise have been resolved, so the last value is save. logical
Now if you resolve the first promise WHEN second is resolved one by one you are able to correct the problem.
var view = 0;
r = item.contentDetails.duration; // video duration
getViewCount(videoId).done(function(t){
view = t;
dfrd1.resolve(r, view);
});
Check the screenshot:
I change a bit the code to solve the problem.
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();
}
});
来源:https://stackoverflow.com/questions/35606024/repeated-video-duration-values-in-asnyc-to-videoid-youtube-api-v3