利用YouTube数据API,我们可以进行查询以获取属于以下请求的用户的前50个视频(通过单个查询可获得的最大结果数):https://www.googleapis.com/youtube/v3/search?key={access_key}&channelId={users_id}&part=id&order=date&maxResults=50&type=video
如果视频超过50个,则生成的JSON将具有nextPageToken
字段,要获取接下来的50个视频,我们可以将&pageToken={nextPageToken}
附加到上述请求中,从而产生下一个包含50个视频的页面。这可以重复,直到nextPageToken
字段不再存在。
这是我使用fetch API编写的一个简单的JavaScript函数,用于获取由nextPageToken
参数(或缺少参数)指定的单个视频页面。
function getUploadedVideosPage(nextPageToken) {
return new Promise((resolve, reject) => {
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;
fetch(apiUrl)
.then((response) => {
response.json()
.then((data) => {
resolve(data);
});
});
});
}
现在,我们需要一个包装器函数,只要有一个
getUploadedVideosPage
,它就会迭代地调用nextPageToken
。这是我的“工作中”,尽管很危险(稍后会详细介绍)。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);
});
}
});
}
“危险”方面是for循环的条件,理论上应该是无限
for(;;)
,因为我们没有预定义的方式来确切知道要进行多少次迭代,而终止循环的唯一方法应该是使用声明。但是,当我以这种方式实现它时,它实际上是无限的,并且永远不会终止。因此,为什么我要对20,000次迭代进行硬编码,并且看起来可行,但是我不相信该解决方案的可靠性。我希望这里的人可以阐明如何实现没有预定义终止条件的迭代Promise链。
最佳答案
您可以使用一个可自行调用的函数来完成全部操作。
您还使用explicit promise construction anti-pattern将fetch()
包装在new Promise
中,因为fetch()
已经返回了promise
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'));
关于javascript - 以编程方式获取属于用户的所有YouTube视频,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53892304/