我正在尝试为youtube用户制作每个视频观看次数的json对象。
首先我正在进行api调用以从特定通道获取所有视频ID,这些被推送到空数组。然后,我遍历所有视频ID,为每个视频进行多次API调用,以获取有关视图的数据。
现在每个视频都有自己的API调用,我似乎无法找到一种方法来组合单个对象中所有调用的所有数据。
我确信这不是这样做的方式,这就是为什么我希望你们能推荐我更好的解决这个问题的方法。
谢谢!
var channelId = 'UCO1cgjhGzsSYb1rsB4bFe4Q'
var url = 'https://www.googleapis.com/youtube/v3/search?key=' + apiKey + '&channelId=' + channelId + '&part=snippet,id&order=date&maxResults=20'
fetch(url).then((resp) => resp.json()).then(function(data) {
var videoIds = []
for (var i = 0; i < data.items.length; i++) {
videoIds.push(data.items[i].id.videoId)
}
return videoIds
}).then(function(ids) {
var urls = []
for (var i = 0; i < ids.length; i++) {
urls.push('https://www.googleapis.com/youtube/v3/videos?part=statistics&id=' + ids[i] + '&key=' + apiKey)
}
return urls
}).then(function(urls) {
for (var i = 0; i < urls.length; i++) {
fetch(urls[i]).then((resp) => resp.json()).then(function(data) {
console.log(data)
})
}
我设法通过使用另一个fetch url和d3.json函数来解决这个问题。
var search = 'https://www.googleapis.com/youtube/v3/search?key=' + apiKey + '&channelId=' + channelId + '&part=snippet,id&order=date&maxResults=5'
var videoIds = []
fetch(search).then((resp) => resp.json())
.then(function(data) {
for (var i = 0; i < data.items.length; i++) {
videoIds.push(data.items[i].id.videoId)
}
return fetch("https://www.googleapis.com/youtube/v3/videos?id=" +videoIds + "&part=snippet%2CcontentDetails%2Cstatistics&key=" + apiKey);
}).then(function(response) {
d3.json(response.url, function(error, data) {
if (error) throw error;
console.log(data)
答案 0 :(得分:0)
您可以创建自己的承诺,用作等待所有并行承诺返回的包装器,一旦它们全部成功返回,您可以resolve
承诺,确认其成功完成或您的罐头reject
承诺并在出现问题时提供错误回复。
请注意,实际工作是在函数getChannelVideos(channelId, config)
内完成的...更确切地说,在Promise体内:
var channelId = 'UCO1cgjhGzsSYb1rsB4bFe4Q'
+ '&channelId='
const baseUrl = 'https://www.googleapis.com/youtube/v3';
let config = {
apiKey: 'yourKeyHere',
part: 'snippet,id',
order: 'date',
maxResults: 20
}
function queryArgs(config) {
let query = '';
config.apiKey ? query += '?key=' + config.apiKey : throw { err: 'You must provided an API KEY' };
config.part ? query += '&part=' + config.part : query;
config.order ? query += '&order=' + config.order : query;
config.maxResults ? query += '&maxResults=' + config.maxResults : query;
return query;
}
function getChannelVideos(channelId, config) {
let URL = baseUrl + '/search' + queryArgs(config) + '&channelId=' + channelId;
// We wrap everything we need to do in a Custom Promise, and return it for a .then(res => { // Success Handler }, err => { // Error Handler })
return new Promise((resolve, reject) => {
// videos to store data from each video request, videoPromises to wait on
let videos = [];
let videoPromises = [];
// Make the Channel Request, followed by a request for each of its videos ( Callback hell)
fetch(URL)
.then((resp) => resp.json())
.then(
data => {
// Declare vars outside map for improved memory management
let currentVideoId;
let currentRequestUrl;
// iterate of the 'data.items' creating a new array of promises (.map(handler) returns a new array of whatever is returned from the handler)
videoPromises = data.items.map(item => {
currentVideoId = item.id.videoId;
currentRequestUrl = baseUrl + '/videos?part=statistics&id=' + currentVideoId + '&key=' + config.apiKey;
return fetch(currentRequest)
.then(
res => {
// Push the Video Response to the videos array (You may want to select something more specific like 'res.data', but this depends on what data you want
videos.push(res);
},
err => {
console.log('Ut-oh - a Video request failed', err);
});
});
});
// Wait for ALL the promises to succeed
Promise.all(videoPromises).then(
success => {
console.log('It\'s all good! Everything was retrieved successfully!');
resolve({
status: 200,
data: {
videos : videos
}
});
},
err => {
reject({
status: 500,
error: err,
message: 'Whomp Whomp Whomp! Something didn\'t work, but the data has what did!',
data: videos
});
})
});
}
// NOW CALL IT
getChannelVideos(channelId, config).then(
res => {
// here are the videos
console.log('videos[]', res.data.videos);
},
err => {
console.log('Darn, maybe next time', err);
});
您还应该看到性能提升,因为调用堆栈中的循环更少且更少。 Array.map(handler)
是JavaScript社区鼓励使用的非常棒的高阶函数。快乐的编码!
答案 1 :(得分:0)
杀死Promise hell
欢迎光临
ES2017
async/await
语法
将您的整个代码更改为此类
async function foo() {
var channelId = 'UCO1cgjhGzsSYb1rsB4bFe4Q'
var url = `https://www.googleapis.com/youtube/v3/search?key=${apiKey}&channelId=${channelId}&part=snippet,id&order=date&maxResults=20`
var resp = await fetch(url)
var data = await resp.json()
var videoIds = []
for (var item of data.items)
videoIds.push(item.id.videoId);
var urls = []
for (var id of videoIds)
urls.push(`https://www.googleapis.com/youtube/v3/videos?part=statistics&id=${id}&key=${apiKey}`);
for (var url of urls) { //This for loop will stop in each url to complete its fetch
let resp = await fetch(url)
let data = await resp.json()
console.log(data)
}
return 'Good Anakin goooood'
}
foo()
.then(msg => console.log(msg))
.catch(e => console.log(e)) //If some Error has been thrown or some fetch was rejected.