Nodejs Meteor-DDP翻译
Nodejs Meteor-DDP翻译
DDP
DDP定义
DDP
是一个客户端
和服务端
之间的协议
,他支持两种操作:
- 由
客户端
向服务端
发起远程过程调用
客户端
订阅数据,在他们变化时,服务器
仍然保持向客户端
发起通知。
本文定义了版本为"pre1
"的DDP
,以上仅仅是粗略的描述而非完整明确的定义。
一般消息结构
无论SockJS
还是WebSockets
,DDP
都将使用较低级别的消息传输方式。(现在,你可以通过URL
连接SockJS
的/sockjs
以及WebSockets
的/websocket
。后者很可能将改变为主应用URL
指定的WebSocket
子协议)
DDP消息
就是指定了EJSON
类型字段的JSON
对象。每个消息
都有一个msg
字段来指定消息类型,或根据其他字段确定消息类型。
建立DDP连接
message分类
connect
(client → server)
session
: string (尝试连接到现有DDP会话)version
: string (拟定的协议版本)support
: [string] (客户端支持的协议版本,按优先顺序排列)
connected
(server → client)
session
: string (DDP会话标识)
failed
(server → client)
version
: string (建议连接协议版本)步骤
服务器
可能会发送一个缺失键名为msg
的初始化message
,如果是这样的,客户端
会忽略它,也不会等待此message
。(此message
是通过SockJS
传输帮助实现代码热部署
的,可能不应该,但目前我们是通过WebSocket
实现的)
客户端
发送connect
消息。- 如果
服务器
允许通信的消息的version
与接收到的connect
消息匹配,服务器
会发送connected
消息。- 否则
服务器
会关闭底层传输,发送failed
消息,告之允许通信的DDP版本以及connect
消息中的support
字段。客户端
建新connect
消息尝试使用不同版本的DDP连接。客户端
会发送众多的connect
消息,直到连接匹配。如果服务器
还不支持,就会忽略掉这些附加信息。
connect
消息的support
字段存储的版本信息是根据客户端的喜好优先级排列的。如果按照这个顺序,由客户端提出的version
不是服务器支持的,服务器必会发送failed
消息,强制客户端切换到更好的版本。
当客户端第一次连接到服务器,他会设置version
为自己最认可的版本。如果有需要,客户端可以记住最终能与服务端匹配的版本。如果服务端能拥有更好的版本或者客户端已经升级,客户端始终依靠服务端发来的failed
消息。
管理数据
message分类
sub
(client → server)
id
: string (订阅的标识符)name
: string (订阅的名字)params
: [EJSON] (可选的订阅参数)
unsub
(client → server)
id
: string (sub
消息中的id)
nosub
(server → client)
id
: string (sub
消息中的id)
error
: Error(可选的错误,订阅错误总结或者订阅不存在等)added
(server → client)
collection
: string (Collecction
名字)id
: string (Document
id)fields
: EJSON (可选的EJSON
值)
changed
(server → client)
collection
: string (Collecction
名字)id
: string (Document
id)fields
: EJSON (可选的EJSON
值)cleared
: [string] (可选的,要删除的字段名)
removed
(server → client)
collection
: string (Collecction
名字)id
: string (Document
id)
ready
(server → client)
subs
: [string] (所有通过sub
传递的id集)
addedBefore
(server → client)
collection
: string (Collecction
名字)id
: string (Document
id)fields
: EJSON (可选的EJSON
值)before
: string/null (Document
添加前的id,或者null表示添加完毕)
movedBefore
(server → client)
collection
: string (Collecction
名字)id
: string (Document
id)before
: string/null (Document
删除前的id,或者null表示删除完毕)
步骤
客户端
指定感兴趣的信息集,发送sub
消息给服务器
。- 在任何时间里,
sub
消息都会被通知到,服务器
再发送数据到客户端。数据包含了added
、changed
、removed
消息。这些消息的本地数据模型将会被跟踪。
added
消息表示了本地数据集的一个Document
。id
字段将被指定为Document
的id
,其他字段将被指定为Document
的其他字段。minimongo
通过特殊的方式将id
转化为_id
以存储到Mongo
的文档集中。changed
消息表示了本地数据集的一个Document
有了新的字段值或某些字段被删除了。id
字段指定了被改变了的Document
的id
,fields
如果存在,表示文档中哪些字段值应该被替换。需要清除的字段应该放在cleared
中以数组的形式呈现。removed
消息表示了本地数据集的一个Document
需要删除了。id
字段指定了需要删除的Document
的id
。- 如果一个
Collection
被订购过,addedBefore
消息可以取代added
消息。包含有该id
的Document
在被添加后可插入before
字段。如果before
字段设置为null
,Document
将被添加,直到结束。对于一个给定的集合,服务器
只应发送added
或addedBefore
消息,而不是两者混合起来发。并且只能发送movedBefore
消息给使用addedBefore
消息的Collection
。注意 : 被订购过的
Collection
的DDP
消息没有使用在Meteor
中,不过今后将会使用。
客户端
保持每一个Collection
的数据。每个订阅不会做自己的数据集,但重复订阅会导致服务器
发送关于Collection
数据的字段联盟。例如,订阅器A说文档x有字段{foo:1,bar:2}
,订阅器B说文档x有{foo:1,baz:3}
,此时客户端
将通知文档x拥有字段{foo:1,bar:2,baz:3}
。如果字段值因为不同订阅器发生冲突,服务器
会发送一个可用的字段值。- 当一个或多个订阅完成首批数据的发送,服务器将发送
ready
消息并伴随他们的id
信息。
远程过程调用
message分类
method
(client → server)
method
: string (方法名)params
: [EJSON] (可选的方法参数)id
: string (方法调用的客户端标识)
result
(server → client)
id
: string (method
消息中的id
)error
: Error (可选的,方法调用时的错误或者方法不存在)result
: EJSON (可选的,方法的返回值)
updated
(server → client)
methods
: string (所有调用过method
消息的id
)
步骤
客户端
发送一个method
消息到服务器
服务端
响应一个result
消息到客户端
,带有方法调用的返回值或者错误信息。- 如果
客户端
接受过订阅,方法调用将直接影响数据。一旦服务端
基于此方式完成所有相应数据的发送,服务器
会发送一个updated
消息给客户端
,并带有所有方法的id集。
错误
result
和nosub
消息中会出现一个可选的error
字段,一个错误消息具备如下字段:
- error : number (错误号)
- reason : string (可选的错误原因)
- details : string (可选的错误详情)
error
用来呈现订阅或者远程调用方法时出现的错误信息,订阅不存在或者调用方法不存在时,也通过这个传递信息。
客户端也能发送其他的错误消息给服务端,这样的消息将以error
为最顶级直接呈现,并包含以下信息:
- 不合法的JSON对象信息
- 未知的
msg
类型 - 其他畸形客户端请求(不包括所需字段)
- 发送第一次
connect
消息或者connect
消息初始化无关的其他内容
这样的error
消息将包含以下字段
- reason : string (描述错误的字符串)
- offendingMessage : ** (包含原来解析正确的消息)
使用
做了两个例子,可以参照这篇文章做一下。
附录
EJSON
是一种嵌入扩展JSON
的JSON
对象。他支持所有平时所见的JSON
类型,同时附加了如下内容:
Dates
{"$date": MILLISECONDS_SINCE_EPOCH}
Binary data:
{"$binary": BASE_64_STRING}
基于64位字符串,有符号+
和/
,没有长度限制。
转义内容,否则看上去更像是EJSON
类型:
{"$escape": THING}
例如,把JSON
值{$date:10000}
装进EJSON
对象中:
{"$escape": {"$date": 10000}}
注意:
转义内容的键必须存放在下级,你也可以再嵌套EJSON
,例如,下面将$date
映射到一个日期对象上:
{"$escape": {"$date": {"$date": 32491}}}
User-specified types
{"$type": TYPENAME, "$value": VALUE}
实现EJSON
应尽量保证键位顺序。如果允许,也可以不必这样。
MongoDB
依赖键位顺序。在MongoDB
中使用EJSON
是,实现的EJSON
必须保持键位顺序。
有关EJSON
的详细信息可以到Meteor
的文档中心-EJSON查阅,或是查看讲解EJSON的视频。
Node.js Meteor-DDP 翻译
DDP 定义
DDP
是 客户端
和 服务端
之间的一种 协议
,它支持两种主要的操作:
- 客户端向服务端发起
远程过程调用
。 - 客户端订阅数据,当数据发生变化时,服务端持续向客户端发送更新。
本文档定义了 DDP
的 pre1
版本,以上内容是对 DDP
的简要描述,而不是完整的定义。
一般消息结构
DDP
消息是具有 EJSON
类型字段的 JSON
对象。每个消息都包含一个 msg
字段,用于指定消息类型,或者根据其他字段确定消息类型。
建立 DDP 连接
客户端和服务器之间通过 connect
、connected
和 failed
消息进行连接。具体步骤如下:
- 客户端发送
connect
消息。 - 如果服务器支持客户端提议的
version
,则发送connected
消息。 - 否则,服务器会关闭连接并发送
failed
消息,指示支持的DDP
版本。
// 示例代码:客户端发送 connect 消息
const ddpClient = new DDPClient({
host: 'localhost',
port: 3000,
autoReconnect: true,
autoReconnectTimer: 500,
maintainCollections: true,
retryOnError: false,
useSockJS: true
});
ddpClient.connect((err) => {
if (err) {
console.error('Connection error:', err);
return;
}
console.log('Connected to DDP server');
});
管理数据
DDP
通过 sub
、unsub
、nosub
、added
、changed
、removed
、ready
、addedBefore
和 movedBefore
消息来管理数据。
- 客户端发送
sub
消息订阅数据。 - 服务器响应
added
、changed
和removed
消息,更新客户端的数据。 - 当订阅完成,服务器发送
ready
消息。
// 示例代码:客户端订阅数据
ddpClient.subscribe('posts', [], (error) => {
if (error) {
console.error('Subscription error:', error);
} else {
console.log('Subscribed successfully');
}
});
远程过程调用
DDP
支持远程过程调用,通过 method
和 result
消息实现。
- 客户端发送
method
消息调用服务端方法。 - 服务端响应
result
消息,返回结果或错误信息。
// 示例代码:客户端调用服务端方法
ddpClient.call('addNumbers', [1, 2], (error, result) => {
if (error) {
console.error('Method call error:', error);
} else {
console.log('Result:', result);
}
});
错误处理
DDP
中的错误信息可以通过 error
字段进行传递,包括错误号、原因和详情。
使用
为了更好地理解 DDP
的使用,可以参考 这篇文章。
附录
EJSON
是一种扩展的 JSON
对象,支持日期、二进制数据和用户自定义类型。
// 示例代码:使用 EJSON
const date = new Date();
const ejsonDate = EJSON.newDate(date.getTime());
console.log(EJSON.stringify(ejsonDate)); // 输出 JSON 字符串
以上是 Node.js Meteor-DDP
的简要翻译和示例代码,希望对您有所帮助。
不错,顶~
DDP (Distributed Data Protocol) 是 Meteor 框架中用于客户端和服务端之间通信的一种协议。它支持两种主要的操作:远程过程调用(Remote Procedure Calls)和订阅数据变更通知。下面是针对 DDP 协议的一些核心概念及其示例代码的简要说明。
建立DDP连接
在 Node.js 中,我们可以使用 ddp
库来连接到 Meteor 服务端。下面是如何发送一个 connect
消息的例子:
const DDP = require('ddp');
let ddp = new DDP({
host: 'localhost',
port: 3000,
autoReconnect: true,
autoReconnectTimer: 500,
maintainCollections: true,
useSockJs: false
});
ddp.connect().then(() => {
console.log('Connected to DDP server.');
}).catch((err) => {
console.error(err);
});
订阅数据
客户端可以通过发送 sub
消息来订阅服务端上的数据。这里假设有一个名为 posts
的集合,我们将订阅其中的所有文档。
ddp.subscribe('posts', [], function() {
let posts = ddp.collections.posts;
if (posts) {
console.log('Subscribed to posts:', posts);
}
});
发起远程过程调用
客户端还可以向服务端发起远程过程调用。这里以调用一个名为 addPost
的方法为例:
ddp.call('addPost', ['Hello World'], function(error, result) {
if (error) {
console.error('Error in method call:', error);
} else {
console.log('Method result:', result);
}
});
处理错误
无论是订阅还是方法调用,都可能产生错误。我们可以处理这些错误来确保程序的健壮性。
ddp.on('error', (error, handle) => {
console.error('DDP Error:', error);
});
以上就是对 Node.js Meteor-DDP
的简要介绍及示例代码。通过这些基本的操作,你可以在客户端和服务端之间实现高效的数据同步和方法调用。