Youtube API、NodeJS 和 Promises 的问题
Trouble with Youtube API, NodeJS, and Promises
我正在为我在 Node.js 中从事的项目的一部分而苦苦挣扎。几周前我第一次开始使用 Node,所以我对它很陌生,而且我对编码的经验也不是很丰富。
我有一个名为 video.js 的库,我想从中获取特定播放列表的视频列表。
我有一个在名为 getVideoList 的控制器中调用的原型函数,它获取播放列表的 ID 以及一些其他信息,然后对 youtube 进行 API 调用并获取结果。
如果结果多于 50 个,则在响应中将有一个 nextPageToken 属性。如果有,那么我将不得不再次调用 API 以便获得下一页结果。 (我认为不可能在一次 API 调用中获取所有视频对象。)
发生的事情的一个例子:
code starts
first loop finishes
promise fulfilled
second loop starts
second loop finishes
...
meanwhile the rest of the code is already moving along to the next function (that needs to have the second loops results added to the data videolist)
截至目前,此代码可以正常执行第一个 API 调用,并将 dataObj 推送到 videoList 中。承诺在循环的其余部分完成之前完成。如果我从 if 语句的第一部分中取出 fulfill(videoList),那么承诺根本就没有实现。
我读了很多书,看起来 Bluebird 可能是正确的方法,但这是我的代码中唯一现在无法正常工作的部分,我不知道它是否可行是否必要,如果是,我对如何在这种情况下实现它感到困惑。
如有任何帮助,我们将不胜感激!
Videos.prototype.getVideoList = function(playlistInfo) {
var playlistId = playlistInfo.playlistId;
var videoList = [];
getVideos = function(playlistId, apiKey, nextPageToken) {
var playlistOptions = {
url: "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails&maxResults=50&playlistId=" + playlistId + apiKey,
method: 'GET'
};
if (nextPageToken) {
playlistOptions.url = playlistOptions.url + '&pageToken=' + nextPageToken
}
return new Promise(function(fulfill, reject){
request(playlistOptions, function(error, results, body){
if (error) { reject(error); };
var result = JSON.parse(body);
for(var i = 0; i < result.items.length; i++){
var dataObj = {};
dataObj.videoId = result.items[i].contentDetails.videoId;
dataObj.title = result.items[i].snippet.title;
if (result.items[i].snippet.thumbnails) {
dataObj.thumbnail = result.items[i].snippet.thumbnails.default.url;
};
videoList.push(dataObj);
};
if (result.nextPageToken){
getVideos(playlistId, apiKey, result.nextPageToken);
fulfill(videoList);
} else {
fulfill(videoList);
}
})
});
}
return getVideos(this.videoTotal, playlistId, this.apiKey);
}
使用 Promise A+ 兼容库(例如 Bluebird),您可以用另一个 promise 解决任何 promise。在您的情况下,解决方案可能很简单:
if (result.nextPageToken){
fulfill(getVideos(playlistId, apiKey, result.nextPageToken));
} else {
fulfill(videoList);
}
不是在第一页上立即解析 videoList,而是解析为下一页的结果(当它们可用时),它将由下一页的结果解析......等等,直到您点击一个没有 PageToken 的页面并且整个链被解析为完整的视频列表。
我正在为我在 Node.js 中从事的项目的一部分而苦苦挣扎。几周前我第一次开始使用 Node,所以我对它很陌生,而且我对编码的经验也不是很丰富。
我有一个名为 video.js 的库,我想从中获取特定播放列表的视频列表。
我有一个在名为 getVideoList 的控制器中调用的原型函数,它获取播放列表的 ID 以及一些其他信息,然后对 youtube 进行 API 调用并获取结果。
如果结果多于 50 个,则在响应中将有一个 nextPageToken 属性。如果有,那么我将不得不再次调用 API 以便获得下一页结果。 (我认为不可能在一次 API 调用中获取所有视频对象。)
发生的事情的一个例子:
code starts
first loop finishes
promise fulfilled
second loop starts
second loop finishes
...
meanwhile the rest of the code is already moving along to the next function (that needs to have the second loops results added to the data videolist)
截至目前,此代码可以正常执行第一个 API 调用,并将 dataObj 推送到 videoList 中。承诺在循环的其余部分完成之前完成。如果我从 if 语句的第一部分中取出 fulfill(videoList),那么承诺根本就没有实现。
我读了很多书,看起来 Bluebird 可能是正确的方法,但这是我的代码中唯一现在无法正常工作的部分,我不知道它是否可行是否必要,如果是,我对如何在这种情况下实现它感到困惑。
如有任何帮助,我们将不胜感激!
Videos.prototype.getVideoList = function(playlistInfo) {
var playlistId = playlistInfo.playlistId;
var videoList = [];
getVideos = function(playlistId, apiKey, nextPageToken) {
var playlistOptions = {
url: "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2CcontentDetails&maxResults=50&playlistId=" + playlistId + apiKey,
method: 'GET'
};
if (nextPageToken) {
playlistOptions.url = playlistOptions.url + '&pageToken=' + nextPageToken
}
return new Promise(function(fulfill, reject){
request(playlistOptions, function(error, results, body){
if (error) { reject(error); };
var result = JSON.parse(body);
for(var i = 0; i < result.items.length; i++){
var dataObj = {};
dataObj.videoId = result.items[i].contentDetails.videoId;
dataObj.title = result.items[i].snippet.title;
if (result.items[i].snippet.thumbnails) {
dataObj.thumbnail = result.items[i].snippet.thumbnails.default.url;
};
videoList.push(dataObj);
};
if (result.nextPageToken){
getVideos(playlistId, apiKey, result.nextPageToken);
fulfill(videoList);
} else {
fulfill(videoList);
}
})
});
}
return getVideos(this.videoTotal, playlistId, this.apiKey);
}
使用 Promise A+ 兼容库(例如 Bluebird),您可以用另一个 promise 解决任何 promise。在您的情况下,解决方案可能很简单:
if (result.nextPageToken){
fulfill(getVideos(playlistId, apiKey, result.nextPageToken));
} else {
fulfill(videoList);
}
不是在第一页上立即解析 videoList,而是解析为下一页的结果(当它们可用时),它将由下一页的结果解析......等等,直到您点击一个没有 PageToken 的页面并且整个链被解析为完整的视频列表。