Meteor 客户端转换带有外部数据的集合 (youtube)
Meteor client-side transform collections with external data (youtube)
我正在开发多租户应用程序。每个应用程序都会有一个视频模块,它需要多个 youtube playlists/channels id 作为输入。
Apps = {_id: "app01", playlists:['PL4IrNZLvgtED4RTH3xCf9085hwqKmb4lM','PLlYqpJ9JE-J8QIlua0KsBIxp-VQLyM_nO']}
Apps = {_id: "app02", playlists:['id22','id23']}
等等。
当用户重定向到地址 localhost:3000/app/:_id 时,应用订阅 Meteor.subscribe('apps',_id).
现在在客户端,我需要呈现一个显示播放列表列表(或频道列表)的页面,其中包含播放列表的名称、播放列表缩略图;然后如果用户单击 name/thumbnail,它会显示另一个页面,其中包含属于 playlist/channel.
的视频列表
我正在做的是让一个助手来检索所有 youtube 播放列表的信息:
Template.Videos.helpers({
myPlaylist:function(){
return Apps.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
doc.date = new Date(); //for testing
doc.videos = [];
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
videos.push(video);
})//end getJSON
}//end for
doc.videos = videos;
console.log('Result:', doc);
return doc;
}
});
}
});
问题出在我的模板中,我可以看到 myPlaylist.date 作为转换的结果,但我看不到 myPlaylist.videos (虽然我看到 console.log 结果有数据)
有没有人知道如何解决这个问题?非常感谢!
正如@Ian Jones 评论的那样,$.getJSON
是异步的,因此 doc.videos
永远不会在您放置 console.log
的地方有值。要解决此问题,请使用 ReactiveVar package:
Template.Videos.onCreated(function() {
this.videos = new ReactiveVar([]);
var self = this;
Apps.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
var videos = self.videos.get();
videos.push(video);
self.videos.set(videos);
})//end getJSON
}//end for
}
});
}
});
Template.Videos.helpers({
myPlaylist:function(){
var instance = Template.instance();
return instance.videos.get();
}
});
感谢您的帮助。我从一开始就不愿意做 reactive-var,但你的回答激励我去做,非常感谢。
这是我的最终代码:
Template.Videos.created = function(){
var instance = this;
instance.videos = new ReactiveVar([]);
instance.autorun(function(){
MenusList.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
var videos = instance.videos.get();
videos.push(video);
instance.videos.set(videos);
})//end getJSON
}//end for
return doc;
}//end transform
});//end findOne
});//end autorun
}
Template.Videos.helpers({
myPlaylist:function(){
var instance = Template.instance();
return instance.videos.get();
}
});
我正在开发多租户应用程序。每个应用程序都会有一个视频模块,它需要多个 youtube playlists/channels id 作为输入。
Apps = {_id: "app01", playlists:['PL4IrNZLvgtED4RTH3xCf9085hwqKmb4lM','PLlYqpJ9JE-J8QIlua0KsBIxp-VQLyM_nO']}
Apps = {_id: "app02", playlists:['id22','id23']}
等等。
当用户重定向到地址 localhost:3000/app/:_id 时,应用订阅 Meteor.subscribe('apps',_id).
现在在客户端,我需要呈现一个显示播放列表列表(或频道列表)的页面,其中包含播放列表的名称、播放列表缩略图;然后如果用户单击 name/thumbnail,它会显示另一个页面,其中包含属于 playlist/channel.
的视频列表我正在做的是让一个助手来检索所有 youtube 播放列表的信息:
Template.Videos.helpers({
myPlaylist:function(){
return Apps.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
doc.date = new Date(); //for testing
doc.videos = [];
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
videos.push(video);
})//end getJSON
}//end for
doc.videos = videos;
console.log('Result:', doc);
return doc;
}
});
}
});
问题出在我的模板中,我可以看到 myPlaylist.date 作为转换的结果,但我看不到 myPlaylist.videos (虽然我看到 console.log 结果有数据)
有没有人知道如何解决这个问题?非常感谢!
正如@Ian Jones 评论的那样,$.getJSON
是异步的,因此 doc.videos
永远不会在您放置 console.log
的地方有值。要解决此问题,请使用 ReactiveVar package:
Template.Videos.onCreated(function() {
this.videos = new ReactiveVar([]);
var self = this;
Apps.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
var videos = self.videos.get();
videos.push(video);
self.videos.set(videos);
})//end getJSON
}//end for
}
});
}
});
Template.Videos.helpers({
myPlaylist:function(){
var instance = Template.instance();
return instance.videos.get();
}
});
感谢您的帮助。我从一开始就不愿意做 reactive-var,但你的回答激励我去做,非常感谢。 这是我的最终代码:
Template.Videos.created = function(){
var instance = this;
instance.videos = new ReactiveVar([]);
instance.autorun(function(){
MenusList.findOne({}, {
transform: function (doc){
playlists = doc.playlists;
for (var i=0;i<playlists.length;i++){
console.log('find playlist: ',playlists[i]);
var url = 'https://gdata.youtube.com/feeds/api/playlists/'+playlists[i]+'?v=2&alt=json';
$.getJSON(url, function(response){
var video={};
video._id = response.feed.yt$playlistId.$t;
video.title = response.feed.title;
video.entry = response.feed.entry;
var videos = instance.videos.get();
videos.push(video);
instance.videos.set(videos);
})//end getJSON
}//end for
return doc;
}//end transform
});//end findOne
});//end autorun
}
Template.Videos.helpers({
myPlaylist:function(){
var instance = Template.instance();
return instance.videos.get();
}
});