简体   繁体   English

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

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

Express implements a server side session object that lets you store data specific to a client. Express实现了一个服务器端会话对象,允许您存储特定于客户端的数据。 How would you do the equivalent in Meteor? 你如何在Meteor中做同等效果的?

strack recommended using a collection. strack推荐使用一个集合。 This would work if the ids of objects in the collection were session_ids that were exposed both server and client side on the connection objects. 如果集合中的对象的id是在连接对象上公开服务器端和客户端的session_id,则这将起作用。

It appears the client and server share a session_id via the LivedataConnection on the client: 客户端和服务器似乎通过客户端上的LivedataConnection共享session_id:

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

and the LivedataSession object on the server: 和服务器上的LivedataSession对象:

self.id = Meteor.uuid();

But the Meteor API doesn't expose these objects. 但Meteor API不会公开这些对象。 What is the correct way of accessing the session information? 访问会话信息的正确方法是什么?

It would be really convenient if a client's Session object synced with a server side Session object unique to the client that is accessible from Meteor#publish and Meteor#methods. 如果客户端的Session对象与可从Meteor#publish和Meteor#方法访问的客户端唯一的服务器端Session对象同步,那将非常方便。

The user-session smart package I wrote for Meteor is designed exactly for this. 我为Meteor编写的用户会话智能包正是为此而设计的。 It provides all the methods of the Meteor Session API (with the exception of setDefault ), and some additional ones as well. 它提供了Meteor Session API的所有方法( setDefault除外)以及一些其他方法。 It's reactive, and all the changes are persistent. 它是被动的,所有的变化都是持久的。 Best of all, it's available both on the client, and on the server with an additional userId argument. 最重要的是,它既可以在客户端上使用,也可以在服务器上使用另外的userId参数。

If you're willing to use the Auth branch of Meteor, this is what I did with some added comments. 如果你愿意使用Meteor的Auth分支,这就是我做的一些补充评论。 I wasn't a fan of Josh's answer because I don't trust clients! 我不是Josh答案的粉丝,因为我不相信客户! They lie. 他们说谎。

In this example, we'll say that each user has a single magical object. 在这个例子中,我们会说每个用户都有一个神奇的对象。 And we refuse to use any information the user can manipulate client side (ie session variables). 我们拒绝使用用户可以操纵客户端的任何信息(即会话变量)。

On Server: 在服务器上:

//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
});

On Client: 在客户端:

//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");

Then, when you want to go and grab your magical object: 然后,当你想去抓住你的魔法物品时:

var magicObject = MagicalObject.findOne().magicalobject;

Notice here that .magicalobject is NOT a typo, it's the parameter we used in self.set -- {magicalobject: magicalObject}. 请注意.magicalobject不是拼写错误,它是我们在self.set中使用的参数 - {magicalobject:magicalObject}。

I apologize for the long answer. 我为这个长期答案道歉。 But to quickly wrap up: what have we done? 但要快速结束:我们做了什么?

On the server, we have a collection of MagicalObjects which the client doesn't have access to. 在服务器上,我们有一组客户端无权访问的MagicalObjects。 Instead, we publish a single object from magical objects -- which we call "magicalObject." 相反,我们从魔法对象发布一个对象 - 我们称之为“魔法对象”。 According to what we set up, each object belongs to one user. 根据我们设置的内容,每个对象属于一个用户。 So it's a user specific object as requested by the op. 所以它是op所要求的用户特定对象。

The client creates a collection (whose name is "magicalObject"), and then gets sent the data when the actual data in the server database changes. 客户端创建一个集合(其名称为“magicalObject”),然后在服务器数据库中的实际数据发生更改时发送数据。 This collection only has one object by design, but that object can have many parameters (eg magicalObject.kazoo or magicalObject.isHarryPotter) or you can store many different objects (eg nonMagicItem). 此集合只有一个设计对象,但该对象可以有许多参数(例如magicalObject.kazoo或magicalObject.isHarryPotter),或者您可以存储许多不同的对象(例如nonMagicItem)。

I think a "meteor" way to do this is: 我认为这样做的“流星”方式是:

On server side create and publish a ClientSession collection 在服务器端创建并发布ClientSession集合

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

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

    return UserSession.find(user);    
});

On client side 在客户端

Session.set('user_id', 42);

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

You now have an application-level UserSession object that is specific to that user that you can put/get stuff. 您现在拥有一个特定于该用户的应用程序级UserSession对象,您可以放置​​/获取内容。

Also, you can manipulate the UserSession collection on the server using Meteor#methods. 此外,您可以使用Meteor#方法在服务器上操作UserSession集合。

One thing to note is that UserSession doesn't work for a user who has not logged in at the client. 需要注意的一点是,UserSession不适用于未在客户端登录的用户。 I faced this scenario, since I wanted creation of a new user's data object to be modified before saving to MongoDB. 我遇到了这种情况,因为我想在保存到MongoDB之前创建一个新用户的数据对象进行修改。 The modification was to add an attribute/field obtained from the URL path of current page (using Iron Route client side route). 修改是添加从当前页面的URL路径获取的属性/字段(使用Iron Route客户端路由)。 But I was receiving this error, 但是我收到了这个错误,

"You cannot use UserSession methods when there is no user logged in." “当没有用户登录时,您无法使用UserSession方法。”

So if your use case is restricted to sharing data between client and server for a logged in user, UserSession package seems to do the job. 因此,如果您的用例仅限于在登录用户的客户端和服务器之间共享数据,则UserSession包似乎可以完成这项工作。

A session behaves a little differently than a collection. 会话与集合的行为略有不同。 If you are truly looking for a session based solution, use the Session.set() method to of course set your values, and retrieve them when needed with Session.get(). 如果您真的在寻找基于会话的解决方案,请使用Session.set()方法来设置您的值,并在需要时使用Session.get()检索它们。

I think that's what the Session is for in meteor-- To store information needed on the client side. 我认为这就是Session在流星中的用途 - 存储客户端所需的信息。

If you need to pass something to the server, maybe put it in a Meteor collection?: 如果您需要将某些内容传递给服务器,可以将其放入Meteor集合中?:

Cookies = new Meteor.collection("cookies")

Otherwise, just use Session . 否则,只需使用Session

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在客户端运行服务器端的 function? - How do you run a function of the server side while on the client side? 您如何有条件地将数据发送到Meteor中的客户端? - How do you conditionally send data to the client in Meteor? 如何将变量从服务器端传递到客户端js Meteor - How do I pass a variable from server side to client side js Meteor 如何在客户端存储临时数据,然后将其发送到服务器 - How to store temporary data at the client-side and then send it to the server 调试流星客户端时,如何查看集合或游标内容? - When debugging meteor client side, how do you view collection or cursor contents? 客户端代理服务器! 你能做到吗? - Client side proxy server! Can you do it? 如何使用Javascript在Meteor的客户端访问模型数据? - How do I access model data on Meteor's client side using Javascript? 如何获取在Meteor上的客户端的subscription方法上发布的数据? - How do I get the data published at client-side's subscribe method on Meteor? 您如何判断网页是客户端渲染还是服务器端渲染 - How do you tell if a web page is client-side or server-side rendering 如何在客户端(JavaScript)上使用服务器端(VB.NET)的返回值? - How do you use a return value from the server side (VB.NET) on the client side (JavaScript)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM