Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Meteor中有条件地向客户端发送数据?_Javascript_Meteor - Fatal编程技术网

Javascript 如何在Meteor中有条件地向客户端发送数据?

Javascript 如何在Meteor中有条件地向客户端发送数据?,javascript,meteor,Javascript,Meteor,我试图弄清楚如何有条件地将数据发送到中的客户端。我有两种用户类型,根据用户类型,它们在客户端上的接口(因此它们需要的数据是不同的) 假设用户类型为顾问或学生。每个用户文档都有类似于角色:“顾问”或角色:“学生” 学生有学生特有的信息,如剩余课时和辅导员,辅导员有价格等 我如何确保客户端的Meteor.user()拥有我需要的信息,而不需要额外的信息?如果我是以学生身份登录,Meteor.user()应该包括剩余会话和顾问,但如果我是以顾问身份登录,则不应包括。我想我搜索的可能是meteor术语中

我试图弄清楚如何有条件地将数据发送到中的客户端。我有两种用户类型,根据用户类型,它们在客户端上的接口(因此它们需要的数据是不同的)

假设用户类型为
顾问
学生
。每个用户文档都有类似于
角色:“顾问”
角色:“学生”

学生有学生特有的信息,如
剩余课时
辅导员
,辅导员有
价格


我如何确保客户端的
Meteor.user()
拥有我需要的信息,而不需要额外的信息?如果我是以学生身份登录,
Meteor.user()
应该包括
剩余会话
顾问
,但如果我是以顾问身份登录,则不应包括。我想我搜索的可能是meteor术语中的有条件发布和订阅。

meteor用户默认情况下仅发布其基本信息,因此您必须使用meteor.publish将这些字段手动添加到客户端。谢天谢地,我们有一个例子向您展示了如何做到这一点:

// server: publish the rooms collection, minus secret info.
Meteor.publish("rooms", function () {
  return Rooms.find({}, {fields: {secretInfo: 0}});
});

// ... and publish secret info for rooms where the logged-in user
// is an admin. If the client subscribes to both streams, the records
// are merged together into the same documents in the Rooms collection.
Meteor.publish("adminSecretInfo", function () {
  return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}});
});
基本上,您希望发布一个通道,在满足条件时将某些信息返回给客户端,在不满足条件时将其他信息返回给客户端。然后在客户端上订阅该频道

在您的情况下,您可能希望在服务器中实现如下功能:

Meteor.publish("studentInfo", function() {
  var user = Meteor.users.findOne(this.userId);

  if (user && user.type === "student")
    return Users.find({_id: this.userId}, {fields: {sessionsRemaining: 1, counselor: 1}});
  else if (user && user.type === "counselor")
    return Users.find({_id: this.userId}, {fields: {pricePerSession: 1}});
});
然后在客户端上订阅:

Meteor.subscribe("studentInfo");
使用字段选项仅从Mongo查询返回所需的字段

Meteor.publish("extraUserData", function () {
  var user = Meteor.users.findOne(this.userId);
  var fields;

  if (user && user.role === 'counselor')
    fields = {pricePerSession: 1};
  else if (user && user.role === 'student')
    fields = {counselor: 1, sessionsRemaining: 1};

  // even though we want one object, use `find` to return a *cursor*
  return Meteor.users.find({_id: this.userId}, {fields: fields});
});
然后在客户机上打电话

Meteor.subscribe('extraUserData');

订阅可以在Meteor中重叠。因此,这种方法的优点在于,向客户端发送额外字段的发布功能与Meteor的幕后发布功能一起工作,后者发送基本字段,如用户的电子邮件地址和个人资料。在客户端上,
Meteor.users
集合中的文档将是两组字段的联合。

由于Meteor.users与任何其他Meteor集合一样是一个集合,因此您实际上可以像任何其他Meteor集合一样细化其公开内容:

Meteor.publish("users", function () {
    //this.userId is available to reference the logged in user 
    //inside publish functions
    var _role = Meteor.users.findOne({_id: this.userId}).role;
    switch(_role) {
        case "counselor":
            return Meteor.users.find({}, {fields: { sessionRemaining: 0, counselor: 0 }});
        default: //student
            return Meteor.users.find({}, {fields: { counselorSpecific: 0 }});
    }
});
然后,在您的客户机中:

Meteor.subscribe("users");
因此,
Meteor.user()
将根据登录用户的角色相应地自动截断

以下是一个完整的解决方案:

if (Meteor.isServer) {
    Meteor.publish("users", function () {
        //this.userId is available to reference the logged in user 
        //inside publish functions
        var _role = Meteor.users.findOne({ _id: this.userId }).role;
        console.log("userid: " + this.userId);
        console.log("getting role: " + _role);
        switch (_role) {
            case "counselor":
                return Meteor.users.find({}, { fields: { sessionRemaining: 0, counselor: 0 } });
            default: //student
                return Meteor.users.find({}, { fields: { counselorSpecific: 0 } });
        }
    });

    Accounts.onCreateUser(function (options, user) {
        //assign the base role
        user.role = 'counselor' //change to 'student' for student data

        //student specific
        user.sessionRemaining = 100;
        user.counselor = 'Sam Brown';

        //counselor specific
        user.counselorSpecific = { studentsServed: 100 };

        return user;
    });
}

if (Meteor.isClient) {
    Meteor.subscribe("users");

    Template.userDetails.userDump = function () {
        if (Meteor.user()) {
            var _val = "USER ROLE IS " + Meteor.user().role + " | counselorSpecific: " + JSON.stringify(Meteor.user().counselorSpecific) + " | sessionRemaining: " + Meteor.user().sessionRemaining + " | counselor: " + Meteor.user().counselor;
            return _val;
        } else {
            return "NOT LOGGED IN";
        }
    };
}
以及HTML:

<body>
    <div style="padding:10px;">
        {{loginButtons}}
    </div>

    {{> home}}
</body>

<template name="home">
    <h1>User Details</h1>
    {{> userDetails}}
</template>

<template name="userDetails">
   DUMP:
   {{userDump}}
</template>

{{loginButtons}}
{{>主页}
用户详细信息
{{>userDetails}
转储:
{{userDump}}

哎呀,我们重叠了。但是,
Meteor.user
在发布函数中不起作用。请看我答案中的变体。我的借口是我在上面写了//伪代码!但你是对的;-)如果用户类型/角色不是互斥的,这将如何工作?(我实际上简化了我的案例)。我的意思是,假设你在写博客,用户有角色(评论主持人、管理员、编辑),你可以是其中的一个或多个。使用这些发布和订阅策略,我如何确保始终发送当前用户的信息,以及他们根据其所有角色需要查看的信息?你是什么意思?你可以用更多的if/else语句来扩展我为不同角色提供的示例代码。我现在得到了一些答案,但我不知道如何选择最好的,因为它们似乎都在表面上起作用。我想我喜欢最简单、最“流星”的版本,它适用于更复杂的情况(即角色不相互排斥等),在这种情况下,你可能应该选择@debergalis的答案,因为他是流星的创造者之一。没有什么比这更像流星了:)一个微妙的提示:如果用户的角色可以动态改变,那么这个发布者不会注意到这一点,也不会改变它发布的字段。如果您需要这样做,您当前必须在
观察
的基础上手动实现它;希望将来Meteor能够以某种方式进行完全反应式发布。另外请注意,由于
Meteor.user()
将在
extraUserData
标记为就绪后更改,因此所有自动运行将重新运行两次:第一次加载登录用户时运行一次,第二次加载
extraUserData
时运行一次。为了避免这种情况,请改用
Meteor.userId()
:它只会更改一次。还要注意,在合并重叠记录集(游标)时,只会比较顶级值。这意味着,如果一个订阅包含
{a:{x:'x'}}
,而另一个订阅包含
{a:{y:'y'}}
(对于具有相同
\u id
)的文档),那么客户端将不会像您所期望的那样获得
{a:{x:'x',y:'y'}
,而是原始文档中的任意一个。请参阅,在中有更好的描述。