您如何在 Meteor 中存储特定于客户端的数据服务器端?

Posted

技术标签:

【中文标题】您如何在 Meteor 中存储特定于客户端的数据服务器端?【英文标题】:How do you store data server side that is specific to a client in Meteor? 【发布时间】:2012-05-06 18:26:18 【问题描述】:

Express 实现了一个服务器端会话对象,可让您存储特定于客户端的数据。你会如何在 Meteor 中做同样的事情?

strack 推荐使用一个集合。如果集合中对象的 id 是在连接对象上同时在服务器端和客户端公开的 session_ids,这将起作用。

看来客户端和服务器通过客户端上的 LivedataConnection 共享一个 session_id:

if (typeof (msg.session) === "string") 
  var reconnected = (self.last_session_id === msg.session);
  self.last_session_id = msg.session;

和服务器上的 LivedataSession 对象:

self.id = Meteor.uuid();

但 Meteor API 不会公开这些对象。访问会话信息的正确方法是什么?

如果客户端的 Session 对象与客户端唯一可从 Meteor#publish 和 Meteor#methods 访问的服务器端 Session 对象同步,那将非常方便。

【问题讨论】:

+1 透明客户端和服务器会话同步。我以为它是这样工作的,但很困惑它不起作用 【参考方案1】:

我为 Meteor 写的 user-session smart package 正是为此而设计的。它提供了 Meteor Session API 的所有方法(setDefault 除外),以及一些额外的方法。它是被动的,所有的变化都是持久的。最重要的是,它在客户端和服务器上都可用,并带有额外的 userId 参数。

【讨论】:

优秀的包装。这就是 Meteor 的 Session 应该是默认的。也更容易处理我提交的问题。发布函数。 这是一个很棒的包。你为什么选择依赖userId?难道不能只依赖sessionId,即使没有登录也可以工作?我还没有看过你的代码。我找了一些小餐馆开始调查,以便更好地了解这一切【参考方案2】:

如果你愿意使用 Meteor 的 Auth 分支,这就是我对一些添加的 cmets 所做的。我不喜欢乔希的回答,因为我不信任客户!他们说谎。

在这个例子中,我们会说每个用户都有一个魔法物品。我们拒绝使用用户可以操纵客户端的任何信息(即会话变量)。

在服务器上:

//Create our database
MagicalObjects = new Meteor.Collection("magicalObjects");

// Publish the magical object for the client
Meteor.publish("get-the-magical-object", function () 

//In the auth branch, server and client have access to this.userId
//And there is also a collection of users server side

var uid =  this.userId();
//I make sure that when I make this connection, I've created a magical object 
//for each user. 

//Let's assume this adds a parameter to magical object for the userId
//it's linked to (i.e. magObject.uid = ~user id~ )

//we grab our current user from the users database, and pass to our function
checkUserHasMagicalItem(Meteor.users.findOne(_id: uid));

var self = this;
console.log('Writing publish');
console.log('uid: ' + this.userId());

var magicalObject = MagicalObjects.findOne(uid: uid);

//Now, I want to know if the magical object is changed -- and update accordingly 
//with its changes -- you might not need this part

//If you don't- then just uncomment these two lines, ignore the rest
//self.set("magicObject", uid, magicalobject: magicalObject);
//self.flush();

//Here, we're going to watch anything that happens to our magical object
//that's tied to our user
var handle = MagicalObjects.find(uid: uid).observe(
    added: function(doc, idx)
           
    //get the latest version of our object
    magicalObject = MagicalObjects.findOne(uid: uid);
    console.log('added object');
    //now we set this server side
    self.set("magicObject", uid, magicalobject: magicalObject);
    self.flush();   
    ,
     //I'm not concerned about removing, but
    //we do care if it is changed
    changed: function(newDoc, idx, oldDoc)
    
    console.log('changed object');
    magicalObject = MagicalObjects.findOne(uid: uid);
    self.set("magicObject", uid, magicalobject: magicalObject);
    self.flush();           
           
//end observe

);

//for when the player disconnects
self.onStop(function() 

    console.log('Stopping');
    handle.stop();

//end onStop
);

//end publish
);

在客户端:

//this is the name of our collection client side
MagicalObject = new Meteor.Collection("magicObject");

//notice the name is equal to whatever string you use when you call
//self.set on the server

//notice, this is the name equal to whatever string you use when you
//call Meteor.publish on the server
Meteor.subscribe("get-the-magical-object");

然后,当你想去拿你的魔法物品时:

var magicObject = MagicalObject.findOne().magicalobject;

请注意,.magicalobject 不是拼写错误,它是我们在 self.set 中使用的参数 -- magicalobject: magicObject。

对于冗长的回答,我深表歉意。但是快速总结一下:我们做了什么?

在服务器上,我们有一个客户端无法访问的 MagicalObjects 集合。相反,我们从魔法对象中发布一个对象——我们称之为“magicalObject”。根据我们的设置,每个对象都属于一个用户。因此,它是操作请求的用户特定对象。

客户端创建一个集合(名称为“magicalObject”),然后在服务器数据库中的实际数据发生变化时发送数据。这个集合在设计上只有一个对象,但该对象可以有许多参数(例如magicObject.kazoo 或magicObject.isHarryPotter),或者您可以存储许多不同的对象(例如nonMagicItem)。

【讨论】:

【参考方案3】:

我认为这样做的“流星”方式是:

在服务器端创建并发布一个 ClientSession 集合

UserSession = new Meteor.Collection("user_sessions");

Meteor.publish('user_sessions', function (user) 

    return UserSession.find(user);    
);

在客户端

Session.set('user_id', 42);

UserSession = new Meteor.Collection("user_sessions");
Meteor.subscribe('user_sessions', Session.get('user_id'));

您现在有一个特定于该用户的应用程序级 UserSession 对象,您可以放置​​/获取内容。

此外,您可以使用 Meteor#methods 在服务器上操作 UserSession 集合。

【讨论】:

如何跟踪用户在没有轮询的情况下断开连接? IDK?我展示的是一个持久的客户端数据(与任何其他 Meteor Collection 没有任何不同。 @joshrtay 似乎您必须进行某种轮询才能可靠地指示用户何时断开连接(假设您的意思是关闭窗口或导航到另一个页面)。见***.com/a/10274212/156060 使用user_id 因为这不是很好。用户只需将user_id 会话变量设置为另一个数字即可从集合中获得另一个结果。 Meteor.publish 有一个 this.userId! 另外 Session.set 并不像我们预期的那样持久化。用户刷新他们的浏览器,我们将不知道他们是谁。【参考方案4】:

需要注意的一点是,UserSession 不适用于尚未在客户端登录的用户。我遇到了这种情况,因为我想在保存到 MongoDB 之前修改创建新用户的数据对象。修改是添加从当前页面的 URL 路径获取的属性/字段(使用 Iron Route 客户端路由)。但是我收到了这个错误,

“当没有用户登录时,你不能使用 UserSession 方法。”

因此,如果您的用例仅限于为登录用户在客户端和服务器之间共享数据,那么 UserSession 包似乎可以胜任。

【讨论】:

【参考方案5】:

会话的行为与集合略有不同。如果您真的在寻找基于会话的解决方案,当然可以使用 Session.set() 方法设置您的值,并在需要时使用 Session.get() 检索它们。

【讨论】:

【参考方案6】:

我认为这就是 Session 在流星中的用途——存储客户端所需的信息。

如果你需要向服务器传递一些东西,也许把它放在一个 Meteor 集合中?:

Cookies = new Meteor.collection("cookies")

否则,请使用Session。

【讨论】:

以上是关于您如何在 Meteor 中存储特定于客户端的数据服务器端?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中获取 Azure 表存储中的所有行?

流星加载脚本,特定于页面的 CSS

如何将特定于类的文件夹中的图像上传到 Azure ML Studio 上的 Azure Blob 存储

您如何在团队环境中维护有用的 SQL 库?

如何在 Thrift 服务中使用特定于 java 的类型?

您可以在 PhoneGap 中添加特定于平台的代码吗?