【问题标题】:Meteor.js Publishing and Subscribing?Meteor.js 发布和订阅?
【发布时间】:2026-02-07 21:35:01
【问题描述】:

好的,所以我对 Meteor.js 有点困惑。我用它创建了一个站点来测试各种概念,它运行良好。删除“不安全”和“自动发布”后,在尝试检索和推送到服务器时会出现多个“拒绝访问”错误。我相信它与以下 sn-p 有关:

Template.posts.posts = function () {
    return Posts.find({}, {sort: {time: -1}});
}

我认为它正在尝试直接访问该集合,它被允许在启用“不安全”和“自动发布”的情况下进行,但一旦它们被禁用,它就会被拒绝访问。另一个我认为有问题的部分:

else {
    Posts.insert({
    user: Meteor.user().profile.name,
    post: post.value,
    time: Date.now(),
});

我认为同样的事情正在发生:它试图直接访问集合,这是不允许的。

我的问题是,我如何重新考虑它以便我不需要启用“不安全”和“自动发布”?

谢谢。

编辑

决赛:

/** 
* Models
*/
Posts = new Meteor.Collection('posts');

posts = Posts

if (Meteor.isClient) {

    Meteor.subscribe('posts');


}

if (Meteor.isServer) {

    Meteor.publish('posts', function() {
        return posts.find({}, {time:-1, limit: 100});
   });


    posts.allow({

        insert: function (document) {
            return true;
        },
        update: function () {
            return false;
        },
        remove: function () {
            return false;
        }

    });

}

【问题讨论】:

  • 是的,您声明了变量“Posts”,但尝试使用服务器上的“posts”访问它。您应该更正错字,因为现在您有一个显示无法运行的代码的问题和答案。

标签: javascript meteor


【解决方案1】:

好的,所以这个问题有两个部分:

自动发布

要在流星中发布数据库,您需要在项目的服务器端和客户端都有代码。假设你已经实例化了集合 (Posts = new Meteor.Collection('posts')),那么你需要

if (Meteor.isServer) {
    Meteor.publish('posts', function(subsargs) {
        //subsargs are args passed in the next section
        return posts.find()
        //or 
        return posts.find({}, {time:-1, limit: 5}) //etc
   })
}

那么对于客户端

if (Meteor.isClient) {
    Meteor.subscribe('posts', subsargs) //here is where you can pass arguments
}

不安全

不安全的目的是允许客户端不加选择地添加、修改和删除它想要的任何数据库条目。但是,大多数时候你不希望这样。删除不安全后,您需要在服务器上设置规则,详细说明谁可以做什么。这两个函数是 db.allow 和 db.deny。例如

if (Meteor.isServer) {
    posts.allow({ 
        insert:function(userId, document) {
            if (userId === "ABCDEFGHIJKLMNOP") {  //e.g check if admin
                return true;
            }
            return false;
        },
        update: function(userId,doc,fieldNames,modifier) {
            if (fieldNames.length === 1 && fieldNames[0] === "post") { //they are only updating the post
                return true;
            }
            return false;
        },
        remove: function(userId, doc) {
            if (doc.user === userId) {  //if the creator is trying to remove it
                return true;
            }
            return false;
        }
    });
}

同样,db.deny 的行为方式完全相同,但 true 的响应表示“不允许此操作”

希望这能回答你所有的问题

【讨论】:

  • 当您说insert:function(userId, document)update: function(userId,doc,fieldNames,modifier) 时,您如何传递这些参数?而且,您是从客户端还是从服务器执行此操作?
  • 您本身并不调用这些函数。他们在某些事件上被流星调用,并由调用者传递这些参数。这有意义吗?
  • Mmkay,所以它们被某些事件调用......但我不确定我是否理解参数是如何传递的。您能否提供(或链接到)一段客户端代码触发插入/更新/删除函数并传递参数的示例?
  • 如果在客户端,你调用了db.update,比如posts.remove({key: value}),那么你在服务端传递给posts.allow({remove: .... })的函数会被调用客户和他们试图删除的文档。如果该函数返回true,则允许他们删除它。否则,文档将保留。 updateinsert 行为相似
  • 您使用 posts.xxxx 调用的客户端函数将自动获取您的 userId 等,然后将其传递给服务器。服务器会用它做一些事情,然后调用适当的 posts.allow 使用它作为参数。