【问题标题】:Meteor Subscriptions ready not working流星订阅准备好不工作
【发布时间】:2016-08-02 18:33:38
【问题描述】:

我已经搜索并尝试了几个小时,但我找不到任何解决方案。

我正在编写一个音乐应用程序,可以在服务器上播放来自 YouTube 的歌曲。我正在下载缩略图并将其存储在cfs:collection 中(因为稍后我需要它的高斯模糊版本)。

我的发布方法如下所示:

Meteor.publish('currentSong', function() {
    return [Playlist.find({'position': 0}), Thumbnails.find()];
});

我有一个版本,它只发布当前歌曲的缩略图,但这导致了更多问题。

在我的 Templates onCreated 方法中,我订阅了该方法(以及其他各种内容)。我已经在 this.autorun() 方法和其他方法之外进行了尝试。

Template.controlpanel.onCreated(function() {
    // subscribe to the publications
    Meteor.subscribe('currentSong');
    Meteor.subscribe('status');
});

然后我有一个模板助手检索缩略图的 URL 以在 <img src="<url>" /> 上下文中实际显示它:

getThumbnail: function() {
    if(Template.instance().subscriptionsReady()){
        var thumbnail = this.thumbnail.getFileRecord();
        if(!$.isEmptyObject(thumbnail)){
            return thumbnail.url({'store': 'Thumbnail'});
        }
    }
}

由于我被要求提供更多代码,这里是来自实际模板的 sn-p

{{#with currentSong}}
<div id="ThumbnailDisplay">     
    <img src="{{getThumbnail}}" alt="{{title}} Thumbnail" id="thumbnail">
</div>
{{/with}}

currentSong 只返回一个数据库条目,监听以下模式:

PlaylistSchema = new SimpleSchema({
    title: {
       type: String,
       label: "titlename"
    },
    url: {
        type: String,
        label: "titleurl"
    },
    duration: {
        type: Number,
        label: "duration"
    },
    file: {
        type: String,
        label: "filepath",
        optional: true
    },
    position: {
        type: Number,
        label: "postion"
    },
    // id to the Thumbnail CFS Collection object
    thumbnail: {
        // type: String,
        type: FS.File,
        label: "thumbnail"
    }
});

您可以在这里看到,{{#with currentSong}} 上下文中的this.thumbnail 指的是存储缩略图及其高斯模糊版本的 FS.File 对象。

问题是,当模板已经加载并且从一首歌曲切换到另一首歌曲时,它可以正常工作。但是当我的播放列表中没有歌曲时,显示部分是不可见的(模板在技术上是渲染的,但所有信息都在 {{#with currentSong}} 块内)。当我插入一首歌曲时,显示屏会“弹出”并显示除缩略图之外的所有内容(歌曲标题、持续时间滑块等)。一旦我重新加载页面,它就在那里。

我正在订阅该收藏。我检查天气订阅是否已准备好或仍然无法正常工作。

我的应用程序中有一些其他部分在 onCreated 上下文中订阅,但仍然必须使用 setTimeout (function(), 100),否则数据尚不可用。

我很确定问题出在屏幕前,我遗漏了某些内容或不完全理解 Meteor 的订阅以及哪个部分是反应性的。但我就是不明白。非常感谢您的帮助。

需要注意的一点是,我知道iron-router 及其功能。我在我的另一个项目中使用过它。但是这个应用程序是一个完全不需要路由的单页应用程序。所以我想限制使用它。

【问题讨论】:

  • 您可能需要显示更多代码以便我们找到问题。具体来说,您如何从数组中的两个不同光标的(相当奇怪的......)发布到 this.thumbnail
  • 我已经编辑了这个问题,以便为您提供更多代码。我希望这有帮助。你觉得出版物的哪一部分很奇怪?什么是正确的方法?
  • 您是否在控制台中遇到任何错误?有时在这些情况下,我发现客户端因错误而停止处理,因为变量未定义 - 例如this.thumbnail 可能在调用 getFileRecord() 时未定义
  • 我刚刚再次检查,不,我没有看到任何错误消息。但是我尝试在助手中添加console.log(thumbnail.url({'store': 'Thumbnail'})),当我输入第一首歌曲(这导致模板“出现”)时,第一条消息给了我正确的 URL,但随后我收到了连续的消息,指出 null 出现来自同一个帮手。这看起来很奇怪。
  • 所以我实际上找到了一个我根本不喜欢的 hacky 解决方案。通过我发现的一些console.log() 语句,在某些时候帮助程序实际上找到了缩略图,但thumbnail.url()return 无效。但是,如果我将这个 return thumbnail.url() 放在 setTimeout(function(){...}, 100) 块中,它就可以工作。所以我的问题是,为什么会有像subscriptionsReady() 这样的东西,最终订阅还没有准备好。在甚至找不到数据的情况下,此函数甚至返回 true。这将是我在这个项目中第三次使用setTimeout hack。

标签: javascript meteor


【解决方案1】:

所以在玩了一会儿之后,问题基本上是,订阅准备好了,但 CollectionFS 文件还没有。

我现在的解决方案是,我有我的助手,被动地设置正确的 URL,除了第一次呈现模板时,它始终有效。

为了解决这个问题,我有一个自动运行功能,可以在歌曲更改时更改图像。

this.autorun(function() {
    if(this.subscriptionsReady()){
        var currentSong = Playlist.findOne({'position': 0});
        if(currentSong ){
            var thumbnail = currentSong.thumbnail.getFileRecord();
            $('#thumbnail').attr('src', thumbnail.url());
        }
    }
}.bind(this));

这可能不是理想的解决方案,但它确实有效。由于某种原因,subscriptionReady 和 CollectionFS 似乎不能很好地协同工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 2018-12-26
    • 2015-11-17
    • 2016-02-17
    • 2012-10-01
    相关资源
    最近更新 更多