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

How do you store data server side that is specific to a client in Meteor?

本文关键字:客户端 数据 服务器端 Meteor 存储      更新时间:2023-09-26

Express 实现了一个服务器端会话对象,允许您存储特定于客户端的数据。你会如何在流星中做等效的事情?

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 不会公开这些对象。访问会话信息的正确方法是什么?

如果客户端的会话对象

与客户端唯一的服务器端会话对象同步,该对象可从 Meteor#publish 和 Meteor#方法访问,这将非常方便。

我为 Meteor 编写的用户会话智能包正是为此而设计的。它提供了 Meteor Session API 的所有方法(setDefault 除外),还有一些额外的方法。它是被动的,所有的变化都是持久的。最重要的是,它既可以在客户端上使用,也可以在服务器上使用,并带有额外的userId参数。

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

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

在服务器上:

//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: magicalObject}。

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

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

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

我认为"

流星"的方法是:

在服务器端创建和发布客户端会话集合

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#方法操作服务器上的用户会话集合。

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

"没有用户登录时,不能使用用户会话方法。"

因此,如果您的用例仅限于在客户端和服务器之间为登录用户共享数据,则UserSession包似乎可以完成这项工作。

会话

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

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

如果您需要将某些内容传递给服务器,可以将其放在Meteor集合中?

Cookies = new Meteor.collection("cookies")

否则,只需使用会话。