简体   繁体   English

在meteor中,pub / sub可以用于任意的内存中对象(不是mongo集合)

[英]In meteor, can pub/sub be used for arbitrary in-memory objects (not mongo collection)

I want to establish a two-way (bidirectional) communication within my meteor app. 我想在我的流星应用程序中建立双向(双向)通信。 But I need to do it without using mongo collections. 但是我需要在不使用mongo集合的情况下完成它。

So can pub/sub be used for arbitrary in-memory objects? 那么pub / sub可以用于任意的内存中对象吗?

Is there a better, faster, or lower-level way? 是否有更好,更快或更低级别的方式? Performance is my top concern. 表现是我​​最关心的问题。

Thanks. 谢谢。

Yes, pub/sub can be used for arbitrary objects. 是的,pub / sub可用于任意对象。 Meteor's docs even provide an example : Meteor的文档甚至提供了一个例子

// server: publish the current size of a collection
Meteor.publish("counts-by-room", function (roomId) {
  var self = this;
  check(roomId, String);
  var count = 0;
  var initializing = true;

  // observeChanges only returns after the initial `added` callbacks
  // have run. Until then, we don't want to send a lot of
  // `self.changed()` messages - hence tracking the
  // `initializing` state.
  var handle = Messages.find({roomId: roomId}).observeChanges({
    added: function (id) {
      count++;
      if (!initializing)
        self.changed("counts", roomId, {count: count});
    },
    removed: function (id) {
      count--;
      self.changed("counts", roomId, {count: count});
    }
    // don't care about changed
  });

  // Instead, we'll send one `self.added()` message right after
  // observeChanges has returned, and mark the subscription as
  // ready.
  initializing = false;
  self.added("counts", roomId, {count: count});
  self.ready();

  // Stop observing the cursor when client unsubs.
  // Stopping a subscription automatically takes
  // care of sending the client any removed messages.
  self.onStop(function () {
    handle.stop();
  });
});

// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");

// client: subscribe to the count for the current room
Tracker.autorun(function () {
  Meteor.subscribe("counts-by-room", Session.get("roomId"));
});

// client: use the new collection
console.log("Current room has " +
            Counts.findOne(Session.get("roomId")).count +
            " messages.");

In this example, counts-by-room is publishing an arbitrary object created from data returned from Messages.find() , but you could just as easily get your source data elsewhere and publish it in the same way. 在此示例中, counts-by-room是发布从Messages.find()返回的数据创建的任意对象,但您可以轻松地将源数据放在其他位置并以相同的方式发布。 You just need to provide the same added and removed callbacks like the example here. 您只需要提供相同的addedremoved回调,例如此处的示例。

You'll notice that on the client there's a collection called counts , but this is purely in-memory on the client; 您会注意到在客户端上有一个名为counts的集合,但这纯粹是在客户端内存中; it's not saved in MongoDB. 它没有保存在MongoDB中。 I think this is necessary to use pub/sub. 我认为这是使用pub / sub的必要条件。

If you want to avoid even an in-memory-only collection, you should look at Meteor.call . 如果你想避免使用仅限内存的集合,你应该看看Meteor.call You could create a Meteor.method like getCountsByRoom(roomId) and call it from the client like Meteor.call('getCountsByRoom', 123) and the method will execute on the server and return its response. 您可以像getCountsByRoom(roomId)一样创建Meteor.method ,并从客户端调用它,如Meteor.call('getCountsByRoom', 123) ,该方法将在服务器上执行并返回其响应。 This is more the traditional Ajax way of doing things, and you lose all of Meteor's reactivity. 这更像是传统的Ajax做事方式,而你失去了Meteor的所有反应。

Just to add another easy solution. 只是添加另一个简单的解决方案 You can pass connection: null to your Collection instantiation on your server. 您可以将connection: null传递给服务器上的Collection实例化。 Even though this is not well-documented, but I heard from the meteor folks that this makes the collection in-memory. 即使这没有详细记录,但我从流星人那里听说这使得这个集合在内存中。

Here's an example code posted by Emily Stark a year ago: 这是一年前由Emily Stark发布的示例代码:

if (Meteor.isClient) {
  Test = new Meteor.Collection("test");
  Meteor.subscribe("testsub");
}

if (Meteor.isServer) {
  Test = new Meteor.Collection("test", { connection: null });
  Meteor.publish("testsub", function () {
    return Test.find();
  });

  Test.insert({ foo: "bar" });
  Test.insert({ foo: "baz" });
}

Edit 编辑

This should go under comment but I found it could be too long for it so I post as an answer. 这应该是评论,但我发现它可能太长了所以我发布作为答案。 Or perhaps I misunderstood your question? 或许我误解了你的问题?

I wonder why you are against mongo . 我想知道你为什么反对mongo I somehow find it a good match with Meteor. 我莫名其妙地发现它与Meteor很匹配。

Anyway, everyone's use case can be different and your idea is doable but not with some serious hacks. 无论如何,每个人的用例可能不同,你的想法是可行的,但不是一些严重的黑客。

if you look at Meteor source code, you can find tools/run-mongo.js , it's where Meteor talks to mongo , you may tweak or implement your adaptor to work with your in-memory objects. 如果你看一下Meteor源代码,你可以找到tools/run-mongo.js ,这是Meteormongo交谈的地方,你可以调整或实现​​你的适配器来处理内存中的对象。

Another approach I can think of, will be to wrap your in-memory objects and write a database logic/layer to intercept existing mongo database communications (default port on 27017), you have to take care of all system environment variables like MONGO_URL etc. to make it work properly. 我能想到的另一种方法是包装你的内存中对象并编写数据库逻辑/层来拦截现有的mongo数据库通信(27017上的默认端口),你必须处理所有系统环境变量,如MONGO_URL等。使其正常工作。

Final approach is wait until Meteor officially supports other databases like Redis . 最后的方法是等到Meteor正式支持像Redis这样的其他数据库。

Hope this helps. 希望这可以帮助。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM