我正在使用https://github.com/Haidy777/node-youtubeAPI-simplifier从Bounty Killers的播放列表中获取一些信息。方式,这个库设置似乎使用Promise via Bluebird(https://github.com/petkaantonov/bluebird),我不太了解。查看BlueBird的初学者指南,提供http://bluebirdjs.com/docs/beginners-guide.html字面上只显示
本文部分或完全未完成。欢迎您创建拉取请求以帮助完成本文。
我可以设置库
var ytapi = require('node-youtubeapi-simplifier');
ytapi.setup('My Server Key');
除了列出有关Bounty Killers的一些信息
ytdata = [];
ytapi.playlistFunctions.getVideosForPlaylist('PLCCB0BFBF2BB4AB1D')
.then(function (data) {
for (var i = 0, len = data.length; i < len; i++) {
ytapi.videoFunctions.getDetailsForVideoIds([data[i].videoId])
.then(function (video) {
console.log(video);
// ytdata.push(video); <- Push a Bounty Killer Video
});
}
});
// console.log(ytdata); This gives []
基本上上面提取了完整的播放列表(通常这里会有一些分页,具体取决于长度)然后,getVideosForPlaylist
的数据会迭代列表并为每个YouTube视频调用getDetailsForVideoIds
。一切都很好。
从中获取数据会产生问题。我想将视频对象推送到ytdata
数组,我不确定最后的空数组是由于作用域还是某些不同步,因此在API调用之前调用console.log(ytdata)
结束。
我如何才能将每个赏金杀手视频纳入ytdata
数组,以便在全球推出?
答案 0 :(得分:2)
在API调用完成之前调用console.log(ytdata)
当然,这就是这里发生的事情,API调用是异步的。一旦您使用异步功能,如果要处理返回的数据,则必须采用异步方式。您的代码可以这样写:
var ytapi = require('node-youtubeapi-simplifier');
ytapi.setup('My Server Key');
// this function return a promise you can "wait"
function getVideos() {
return ytapi.playlistFunctions
.getVideosForPlaylist('PLCCB0BFBF2BB4AB1D')
.then(function (videos) {
// extract all videoIds
var videoIds = videos.map(video => video.videoId);
// getDetailsForVideoIds is called with an array of videoIds
// and return a promise, one API call is enough
return ytapi.videoFunctions.getDetailsForVideoIds(videoIds);
});
}
getVideos().then(function (ydata) {
// this is the only place ydata is full of data
console.log(ydata);
});
我在videos.map(video => video.videoId);
中使用了ES6的箭头功能,如果你的nodejs是v4 +,它应该可以使用。
答案 1 :(得分:1)
console.log(ytdata)应该在FOR循环之后立即执行。在解析promise并且FOR循环执行完成并且尝试预先访问它之前,这些数据不可用,这将为您提供一个空数组。
(您当前的console.log无法正常工作,因为该代码是在解析承诺之前立即执行的)。只有在解决了承诺后才执行THEN块内的代码。
如果你现在或者需要现有的数据,并且对视频的请求需要很长时间,那么你可以一次或根据需要或在一个单独的线程(可能使用网络工程师)请求1个视频吗?你能实现缓存吗?
在用户访问此页面之前,您是否可以在幕后提出请求? (不确定这是一个好主意,但这是一个想法)
您是否可以使用视频缩略图(例如youtube),以便在点击缩略图时开始播放和播放视频?
一些想法......希望这会有所帮助
答案 2 :(得分:1)
ytdata = [];
ytapi.playlistFunctions.getVideosForPlaylist('PLCCB0BFBF2BB4AB1D')
.then(function (data) {
// THE CODE INSIDE THIS THEN BLOCK IS EXECUTED WHEN ALL THE VIDEO IDS HAVE BEEN RETRIEVED AND ARE AVAILABLE
// YOU COULD SAVE THESE TO A DATASTORE IF YOU WANT
for (var i = 0, len = data.length; i < len; i++) {
var videoIds = [data[i].videoId];
ytapi.videoFunctions.getDetailsForVideoIds(videoIds)
.then(function (video) {
// THE CODE INSIDE THIS THEN BLOCK IS EXECUTED WHEN ALL THE DETAILS HAVE BEEN DOWNLOADED FOR ALL videoIds provided
// AGAIN YOU CAN DO WHATEVER YOU WANT WITH THESE DETAILS
// ALSO NOW THAT THE DATA IS AVAILABLE YOU MIGHT WANT TO HIDE THE LOADING ICON AND RENDER THE PAGE! AGAIN JUST AN IDEA, A DATA STORE WOULD PROVIDE FASTER ACCESS BUT YOU WOULD NEED TO UPDATE THE CACHE EVERY SO OFTEN
// ytdata.push(video); <- Push a Bounty Killer Video
});
// THE DETAILS FOR ANOTHER VIDEO BECOMES AVAILABLE AFTER EACH ITERATION OF THE FOR LOOP
}
// ALL THE DATA IS AVAILABLE WHEN THE FOR LOOP HAS COMPLETED
});
// This is executed immediately before YTAPI has responded.
// console.log(ytdata); This gives []