Javascript 以编程方式获取属于用户的所有YouTube视频
利用YouTube数据API,我们可以进行查询,以获得属于具有以下请求的用户的前50个(单次查询可获得的最大结果量)视频:Javascript 以编程方式获取属于用户的所有YouTube视频,javascript,es6-promise,youtube-data-api,Javascript,Es6 Promise,Youtube Data Api,利用YouTube数据API,我们可以进行查询,以获得属于具有以下请求的用户的前50个(单次查询可获得的最大结果量)视频:https://www.googleapis.com/youtube/v3/search?key={access\u key}&channelId={users\u id}&part=id&order=date&maxResults=50&type=video 如果有50多个视频,那么生成的JSON将有一个nextPageToken字段,为了获得接下来的50个视频,我们可以将
https://www.googleapis.com/youtube/v3/search?key={access\u key}&channelId={users\u id}&part=id&order=date&maxResults=50&type=video
如果有50多个视频,那么生成的JSON将有一个nextPageToken
字段,为了获得接下来的50个视频,我们可以将&pageToken={nextPageToken}
附加到上述请求中,生成下一页的50个视频。这可以重复,直到不再存在nextPageToken
字段
下面是我使用fetchapi编写的一个简单JavaScript函数,用于获取nextPageToken
参数指定的单个视频页面
现在我们需要一个包装器函数,只要我们有一个nextPageToken
,它就会迭代调用getUploadedVideosPage
。下面是我的“正在工作”尽管很危险(稍后将详细介绍)的实现
function getAllUploadedVideos() {
return new Promise((resolve, reject) => {
let dataJoined = [];
let chain = getUploadedVideosPage();
for(let i = 0; i < 20000; ++i) {
chain = chain
.then((data) => {
dataJoined.push(data);
if(data.nextPageToken !== undefined)
return getUploadedVideosPage(data.nextPageToken);
else
resolve(dataJoined);
});
}
});
}
函数getAllUploadedVideos(){
返回新承诺((解决、拒绝)=>{
让dataJoined=[];
let chain=getUploadedVideosPage();
对于(设i=0;i<20000;++i){
链子
。然后((数据)=>{
推送(数据);
if(data.nextPageToken!==未定义)
返回getUploadedVideosPage(data.nextPageToken);
其他的
解决(数据连接);
});
}
});
}
“危险”方面是for循环的条件,理论上它应该是无限的for(;)
,因为我们没有预定义的方法来确切地知道要进行多少次迭代,而终止循环的唯一方法应该是使用resolve
语句。然而,当我以这种方式实现它时,它确实是无限的,永远不会终止
因此,我硬编码了20000次迭代,它似乎可以工作,但我不相信这个解决方案的可靠性。我希望这里有人能为如何实现这个没有预定义终止条件的迭代承诺链提供一些帮助。完全摆脱for循环。大概是这样的:
function getAllUploadedVideos() {
return new Promise((resolve, reject) => {
let dataJoined = [];
function getNextPage(nextPageToken) {
return new Promise((resolve, reject) => {
getUploadedVideosPage(nextPageToken)
.then((data) => {
dataJoined.push(data);
if(data.nextPageToken !== undefined) {
resolve(data.nextPageToken);
}
else {
reject();
}
})
.catch((err) => {
// Just in case getUploadedVideosPage errors
reject(err);
});
});
}
getNextPage()
.then((nextPageToken) => {
getNextPage(nextPageToken);
})
.catch(() => {
// This will hit when there is no more pages to grab
resolve(dataJoined);
});
});
}
完全摆脱for循环。大概是这样的:
function getAllUploadedVideos() {
return new Promise((resolve, reject) => {
let dataJoined = [];
function getNextPage(nextPageToken) {
return new Promise((resolve, reject) => {
getUploadedVideosPage(nextPageToken)
.then((data) => {
dataJoined.push(data);
if(data.nextPageToken !== undefined) {
resolve(data.nextPageToken);
}
else {
reject();
}
})
.catch((err) => {
// Just in case getUploadedVideosPage errors
reject(err);
});
});
}
getNextPage()
.then((nextPageToken) => {
getNextPage(nextPageToken);
})
.catch(() => {
// This will hit when there is no more pages to grab
resolve(dataJoined);
});
});
}
如果适用,您可以通过一个调用自身的函数来完成这一切 您还在
newpromise
中使用包装fetch()
,因为fetch()
已经返回了一个承诺
function getVideos(nextPageToken, results = []) {
let apiUrl = 'https://www.googleapis.com/youtube/v3/search?key={access_key}&channelId={users_id}&part=id&order=date&maxResults=50&type=video';
if (nextPageToken) {
apiUrl += '&pageToken=' + nextPageToken;
}
// return fetch() promise
return fetch(apiUrl)
.then(response => response.json())
.then(data => {
// merge new data into final results array
results = results.concat(data);
if (data.nextPageToken !== undefined) {
// return another request promise
return getVideos(data.nextPageToken, results);
} else {
// all done so return the final results
return results
}
});
}
// usage
getVideos().then(results=>{/*do something with all results*/})
.catch(err=>console.log('One of the requests failed'));
如果适用,您可以通过一个调用自身的函数来完成这一切 您还在
newpromise
中使用包装fetch()
,因为fetch()
已经返回了一个承诺
function getVideos(nextPageToken, results = []) {
let apiUrl = 'https://www.googleapis.com/youtube/v3/search?key={access_key}&channelId={users_id}&part=id&order=date&maxResults=50&type=video';
if (nextPageToken) {
apiUrl += '&pageToken=' + nextPageToken;
}
// return fetch() promise
return fetch(apiUrl)
.then(response => response.json())
.then(data => {
// merge new data into final results array
results = results.concat(data);
if (data.nextPageToken !== undefined) {
// return another request promise
return getVideos(data.nextPageToken, results);
} else {
// all done so return the final results
return results
}
});
}
// usage
getVideos().then(results=>{/*do something with all results*/})
.catch(err=>console.log('One of the requests failed'));
调用resolve后返回
?更改resolve(数据连接)代码>到返回解析(dataJoined)代码>没有解决它被卡在无限循环中的问题。为什么有for循环?仅仅让递归完成它的任务还不够吗?我推测递归可能是一条出路,不幸的是,我的递归技能已经“生锈”了。如果您能演示递归方法,我将不胜感激。如果我之前的评论含糊不清,我将深表歉意。我的意思是,我希望getUploadedVideosPage返回页面的结果,这些结果与使用下一个页面标记调用getUploadedVideosPage的剩余结果连接在一起。没有循环。只是getUploadedVideosPage在表格中调用自己。在调用resolve后返回?更改resolve(dataJoined)代码>到返回解析(dataJoined)代码>没有解决它被卡在无限循环中的问题。为什么有for循环?仅仅让递归完成它的任务还不够吗?我推测递归可能是一条出路,不幸的是,我的递归技能已经“生锈”了。如果您能演示递归方法,我将不胜感激。如果我之前的评论含糊不清,我将深表歉意。我的意思是,我希望getUploadedVideosPage返回页面的结果,这些结果与使用下一个页面标记调用getUploadedVideosPage的剩余结果连接在一起。没有循环。只是getUploadedVideosPage在thenable中调用自己。它更像是一个“getNextPage”,而不是“getNextVideo”,但基本上是正确的想法。也许“getNextVideos”是下一页的50个视频,每一个请求都会收到。是的,如果合适的话,请说出名字。但这让它一直拉新页面直到用完,而不需要任意迭代。更新为“getNextPage”,它更像是“getNextPage”,而不是“getNextVideo”,但基本上是正确的想法。也许“getNextVideos”是下一页的50个视频,每一个请求都会收到。是的,如果合适的话,请说出名字。但这让它一直拉新页面,直到它用完为止,而不需要任意迭代。更新为“getNextPage”,感谢您提供了非常干净的解决方案。我肯定还有一些关于承诺机制的阅读。干杯因此,这里要重点关注的主要问题是,要么返回一个保持链继续运行的承诺,要么返回数据到最后的then()
感谢您提供了非常干净的解决方案。我肯定还有一些关于承诺机制的阅读。干杯因此,这里要重点关注的主要问题是返回一个保持链运行的承诺,或者返回数据到最后的then()