对Meteor感到困惑:如何在不写入数据库的情况下向所有客户端发送数据?

时间:2013-07-23 12:49:27

标签: meteor

我实际上已经玩弄了Meteor一段时间,但我意识到我仍然缺乏一些(或很多!)对这个主题的理解。

例如,这是一个使用node.js / express / socket.io进行简单实时聊天的教程:http://net.tutsplus.com/tutorials/javascript-ajax/real-time-chat-with-nodejs-socket-io-and-expressjs/

在上面的示例中,通过socket.io,Web服务器接收一些数据并将其传递到所有连接的客户端 - 所有这些都没有任何数据库访问。

使用Meteor,在我看过的所有示例中,通过写入mongodb来更新客户端,mongodb然后更新所有客户端。但是,如果我不需要将数据写入数据库呢?将数据传递给所有客户端似乎是一个昂贵的步骤。

我确信我在这里遗漏了一些东西。更新所有客户端的Meteor方法是什么(比如使用简单的聊天应用程序),但不需要先花费数据写入数据库?

谢谢!

4 个答案:

答案 0 :(得分:10)

目前还没有正式的方法将数据发送给客户而不将其写入集合。它在流星中有点小问题,因为当没有可写入的地方时,将数据发送到多个客户端的步骤来自多个流星一起使用时。即,从一个流星发送的项目不会在另一个流星上订阅。

有一个使用Meteor Streams(http://meteorhacks.com/introducing-meteor-streams.html)的临时解决方案可以让你做你想做的事情,而不用同时写入数据库。

如果您想了解一些技术细节,还可以在流星谈话(https://groups.google.com/forum/#!topic/meteor-talk/Ze9U9lEozzE)上进行相当广泛的讨论。当链接器分支合并到主服务器时,对于单个服务器

,这实际上是可能的

这里有一个虚拟收藏的方法,它不完美,但它可以做到直到Meteor有更完美的方式完成它。

Meteor.publish("virtual_collection", function() {
    this.added("virtual_coll", "some_id_of_doc", {key: "value"});

    //When done
    this.ready()
});

然后在客户端订阅:

var Virt_Collection = new Meteor.Collection("virtual_coll");
Meteor.subscribe("virtual_collection");

然后您可以在订阅完成时运行它:

Virt_Collection.findOne();
=> { _id: "some_id_of_doc", key: "value"}

这有点乱,但您也可以使用它来更新或删除集合。至少这种方式你不会使用任何插件或包。

有关详细信息和视频示例,请参阅:https://www.eventedmind.com/posts/meteor-how-to-publish-to-a-client-only-collection

答案 1 :(得分:6)

服务器上的发布功能将数据发送给客户端。它有一些方便的快捷方式来从数据库发布查询结果,但您不必使用它们。 publish函数有this.added(),this.removed()和this.changed(),允许您发布您选择的任何内容。然后客户订阅并接收已发布的数据。

例如:

if ( Meteor.isClient ){
  var someMessages = new Meteor.Collection( "messages" );  //messages is name of collection on client side
  Meteor.subscribe ( "messagesSub" );  //messagesSub tells the server which publish function to request data from

  Deps.autorun( function(){
    var message = someMessages.findOne({});
    if ( message )  console.log( message.m ); // prints This is not from a database
  });
}

if (Meteor.isServer ) {
  Meteor.publish( "messagesSub", function(){
    var self = this;
    self.added ( "messages", "madeUpId1", { m: "This is not from a database"} ); //messages is the collection that will be published to
    self.ready();
  });
}

meteor docs中有一个例子解释here和另一个例子here。我还有an example在客户端之间共享数据而不使用数据库只是为了教自己如何发布和订阅。没有使用任何东西,只有基本的流星。

答案 2 :(得分:3)

可以使用Meteor的liveata软件包(他们的DDP实现),而无需服务器上的数据库。这是demoed by Avital Oliver,而我在下面指出相关部分。

魔术发生在这里:

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

if (Meteor.isClient) {
    TransientNotes = new Meteor.Collection("transientNotes");
    Meteor.subscribe("transientNotes");
}

设置connection: null指定没有连接(请参阅Meteor文档)。


Akshat建议使用流。由于缺乏声誉,我无法回复他的评论,所以我会把它放在这里。他链接到的包裹不再被主动维护(参见作者tweet)。我推荐使用yuukan:streamy(在Atmosphere上查找)包或者使用Meteor本身使用的底层SockJS lib - 您可以通过浏览Meteor代码了解如何执行此操作,并查看Meteor.server.Stream_server和使用Meteor.connection._stream,这是Streamy包的功能。

我测试了Streamy聊天示例的一个实现,发现性能可以忽略不计,但这只是在基本测试中。使用第一种方法,您可以获得最小化实施(例如查找)和流星反应性的好处。使用Streamy可以实现的反应性,但是可以通过使用ReactiveVar等来实现。

答案 3 :(得分:1)

有办法!至少从理论上讲,Meteor在客户端和服务器之间同步的协议称为DDP。规范是here

虽然有一些例子herehere的人实现了他们自己的DDP客户端,但我恐怕还没有看到DDP服务器的实现示例。但我认为该协议很简单,并且可能会认为实施起来并不那么难。