简体   繁体   中英

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.

So can pub/sub be used for arbitrary in-memory objects?

Is there a better, faster, or lower-level way? Performance is my top concern.

Thanks.

Yes, pub/sub can be used for arbitrary objects. Meteor's docs even provide an example :

// 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. You just need to provide the same added and removed callbacks like the example here.

You'll notice that on the client there's a collection called counts , but this is purely in-memory on the client; it's not saved in MongoDB. I think this is necessary to use pub/sub.

If you want to avoid even an in-memory-only collection, you should look at 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. This is more the traditional Ajax way of doing things, and you lose all of Meteor's reactivity.

Just to add another easy solution. You can pass connection: null to your Collection instantiation on your server. 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:

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 . I somehow find it a good match with 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.

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.

Final approach is wait until Meteor officially supports other databases like Redis .

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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