将数据推送到 Promise 之外的数组
Getting data pushed to an array outside of a Promise
我正在使用 https://github.com/Haidy777/node-youtubeAPI-simplifier to grab some information from a playlist of Bounty Killers. The way, this library is setup seems to use Promise via Bluebird (https://github.com/petkaantonov/bluebird) which I don't know much about. Looking up the Beginner's Guide for BlueBird gives http://bluebirdjs.com/docs/beginners-guide.html 字面上只是显示
This article is partially or completely unfinished. You are welcome to create pull requests to help completing this article.
我可以设置库
var ytapi = require('node-youtubeapi-simplifier');
ytapi.setup('My Server Key');
以及列出赏金杀手的一些信息
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
数组,我不确定末尾的空数组是由于范围界定还是某些不同步导致 console.log(ytdata)
在 [=31 之前被调用=] 通话结束。
我如何才能将每个赏金杀手视频放入 ytdata
数组以供全球使用?
console.log(ytdata) 应该紧接在 FOR 循环之后。在承诺得到解决并且 FOR 循环执行完成之前,此数据不可用,并且尝试事先访问它会给你一个空数组。
(您当前的 console.log 不起作用,因为该代码在 promise 解决之前立即执行)。只有 THEN 块内的代码在 promise 被解析后执行。
如果您现在或尽快需要可用的数据并且视频请求需要很长时间,那么您可以一次请求 1 个视频或按需或在单独的线程(可能使用网络工作者)上请求 1 个视频吗?你能实现缓存吗?
你能在用户访问这个页面之前在幕后预先提出请求吗? (不确定这是个好主意,但确实是个主意)
您能否使用视频缩略图(就像 youtube 那样)以便在单击缩略图时开始流式传输和播放视频?
一些想法...希望对您有所帮助
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 []
console.log(ytdata) gets called before the API calls are finished
发现,这正是这里发生的事情,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+,它应该可以工作。
我正在使用 https://github.com/Haidy777/node-youtubeAPI-simplifier to grab some information from a playlist of Bounty Killers. The way, this library is setup seems to use Promise via Bluebird (https://github.com/petkaantonov/bluebird) which I don't know much about. Looking up the Beginner's Guide for BlueBird gives http://bluebirdjs.com/docs/beginners-guide.html 字面上只是显示
This article is partially or completely unfinished. You are welcome to create pull requests to help completing this article.
我可以设置库
var ytapi = require('node-youtubeapi-simplifier');
ytapi.setup('My Server Key');
以及列出赏金杀手的一些信息
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
数组,我不确定末尾的空数组是由于范围界定还是某些不同步导致 console.log(ytdata)
在 [=31 之前被调用=] 通话结束。
我如何才能将每个赏金杀手视频放入 ytdata
数组以供全球使用?
console.log(ytdata) 应该紧接在 FOR 循环之后。在承诺得到解决并且 FOR 循环执行完成之前,此数据不可用,并且尝试事先访问它会给你一个空数组。
(您当前的 console.log 不起作用,因为该代码在 promise 解决之前立即执行)。只有 THEN 块内的代码在 promise 被解析后执行。
如果您现在或尽快需要可用的数据并且视频请求需要很长时间,那么您可以一次请求 1 个视频或按需或在单独的线程(可能使用网络工作者)上请求 1 个视频吗?你能实现缓存吗?
你能在用户访问这个页面之前在幕后预先提出请求吗? (不确定这是个好主意,但确实是个主意)
您能否使用视频缩略图(就像 youtube 那样)以便在单击缩略图时开始流式传输和播放视频?
一些想法...希望对您有所帮助
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 []
console.log(ytdata) gets called before the API calls are finished
发现,这正是这里发生的事情,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+,它应该可以工作。