10

我正在 Meteor 中编写一个数据敏感的应用程序,并试图限制客户端访问尽可能多的信息。因此,我想在服务器端实现一种计算登录和匿名用户数量的方法。

我尝试了多种方法。第一个是在这个问题Server cleanup after a client disconnects中概述,这表明挂钩:

this.session.socket.on("close")

但是,当我这样做并尝试更改集合时,它抛出了“Meteor 代码必须始终在 Fiber 中运行”错误。我认为这个问题是因为一旦套接字关闭,Fiber 就会被杀死,所以访问数据库是不可能的。当在服务器上调用 Collection.insert 作为可能的解决方案时, OP 指出“流星代码必须始终在 Fiber 中运行”,但根据对答案的评论,我不确定这是否是最好的方法。

然后我尝试在变量上自动运行:

Meteor.default_server.stream_server.all_sockets().length

但是似乎从未调用过自动运行,因此我假设该变量不是反应性上下文,并且我不确定如何使其成为一个。

最后一个想法是做一个keepalive风格的事情,但这似乎完全违背了Meteor哲学的本质,我认为我只会作为绝对的最后手段使用。

我在console.log上做了一个函数this.session.socket,唯一可能的其他函数是.on("data"),但是当套接字关闭时不会调用它。

我在这里有点茫然,所以任何帮助都会很棒,谢谢。

4

3 回答 3

8

为了完整起见,最好将上面的两个答案结合起来。换句话说,请执行以下操作:

这可能是在 Meteor 中实现这一点的规范方式。我已经将它创建为一个智能包,您可以使用 Meteorite 安装它:https ://github.com/mizzao/meteor-user-status

于 2013-06-21T20:02:02.223 回答
3

感谢 Sorhus 的提示,我设法解决了这个问题。他的回答包含心跳,我很想避免。然而,它包含了使用 Meteor 的“bindEnvironment”的技巧。这允许访问集合,否则将无法访问。

Meteor.publish("whatever", function() {
  userId = this.userId;
  if(userId) Stats.update({}, {$addToSet: {users: userId}});
  else Stats.update({}, {$inc: {users_anon: 1}});

  // This is required, because otherwise each time the publish function is called,
  // the events re-bind and the counts will start becoming ridiculous as the functions
  // are called multiple times!
  if(this.session.socket._events.data.length === 1) {

    this.session.socket.on("data", Meteor.bindEnvironment(function(data) {
      var method = JSON.parse(data).method;

      // If a user is logging in, dec anon. Don't need to add user to set,
      // because when a user logs in, they are re-subscribed to the collection,
      // so the publish function will be called again.
      // Similarly, if they logout, they re-subscribe, and so the anon count
      // will be handled when the publish function is called again - need only
      // to take out the user ID from the users array.
      if(method === 'login')
        Stats.update({}, {$inc: {users_anon: -1}});

      // If a user is logging out, remove from set
      else if(method === 'logout')
        Stats.update({}, {$pull: {users: userId}});

    }, function(e) {
      console.log(e);
    }));

    this.session.socket.on("close", Meteor.bindEnvironment(function() {
      if(userId === null || userId === undefined) 
        Stats.update({}, {$inc: {users_anon: -1}});
      else
        Stats.update({}, {$pull: {users: userId}});
    }, function(e) {
      console.log("close error", e);
    }));
  }
}
于 2013-01-04T18:27:29.253 回答
2

查看 GitHub 项目howmanypeoplearelooking

Meteor 应用程序测试以显示当前有多少用户在线。

于 2012-12-03T03:03:53.193 回答