## 發布和訂閱
Meteor 服務端可以通過`Meteor.publish`發布文檔集,同時客戶端可以通過`Meteor.subscribe`訂閱這些發布。 任何客戶端訂閱的文檔都可以通過`find`方法進行查詢使用。
默認情況下,每個新創建的 Meteor 應用包含有 autopublish 包,它會自動為每個客戶端發布所有可用的文檔。 為了可以更細化的控制不同客戶端所接收的數據文檔,首先應該在終端移除 autopublish:
```
$ meteor remove autopublish
```
現在,你可以使用`Meteor.publish` 和 `Meteor.subscribe` 來控制不同的文檔從服務端推送到不同的客戶端了。
### [Meteor.publish(name, func)](#/basic/Meteor-publish)
Server
Publish a record set.
#### Arguments
name String
Name of the record set. If `null`, the set has no name, and the record set is automatically sent to all connected clients.
func Function
Function called on the server each time a client subscribes. Inside the function, `this` is the publish handler object, described below. If the client passed arguments to `subscribe`, the function is called with the same arguments.
將數據發布到客戶端,通過在服務端調用 Meteor.publish,需要傳入兩個參數:該記錄集的名稱,以及一個會在每一次客戶端訂閱該記錄集的時候被調用的發布功能函數。
發布功能通過返回在一些`collection`調用`collection.find(query)`的結果。通過`query`來限制發布的文檔集:
```
// 發布已登錄用戶的文章集合
Meteor.publish("posts", function () {
return Posts.find({ createdBy: this.userId });
});
```
你可以發布來自多個collection的文檔,通過返回一個`collection.find` 結果集合:
```
// 發布一個單獨的文章和對應的評論
Meteor.publish("postAndComments", function (postId) {
// 檢查參數
check(postId, String);
return [
Posts.find({ _id: postId }),
Comments.find({ postId: roomId })
];
});
```
在發布功能里,`this.userId`是當前登錄用戶的`_id`, 在某些文檔僅對特定用戶可見時,可以用其來過濾集合。 如果客戶端登錄的用戶發生改變,發布功能也將自動使用新的`userId`,所以新用戶無法訪問任何只限于之前登錄用戶的文檔。
### [Meteor.subscribe(name, [arg1, arg2...], [callbacks])](#/basic/Meteor-subscribe)
Client
Subscribe to a record set. Returns a handle that provides `stop()` and `ready()` methods.
#### Arguments
name String
Name of the subscription. Matches the name of the server's `publish()` call.
arg1, arg2... Any
Optional arguments passed to publisher function on server.
callbacks Function or Object
Optional. May include `onStop` and `onReady` callbacks. If there is an error, it is passed as an argument to `onStop`. If a function is passed instead of an object, it is interpreted as an `onReady` callback.
客戶端調用 `Meteor.subscribe`來訂閱服務端發布的文檔集合。 客戶端可以進一步過濾文檔集合通過調用[`collection.find(query)`](#find). 當任何通過發布功能發布的可訪問的數據在服務端發生改變時,發布功能會自動返回和更新發布的文檔集合推送給客戶端。
`onReady`回調函數在服務端已經發送了訂閱的所有初始化數據時被調用,無需傳入任何參數。 `onStop`訂閱不管以任何原因被終止時調用 ;如果訂閱失敗是由于服務端錯誤,它將收到一個[`Meteor.Error`](#meteor_error)。
`Meteor.subscribe` 返回一個訂閱句柄,是一個包含以下方法的對象:
stop()
取消訂閱。這通常會導致服務器引導客戶端從客戶端緩存中刪除訂閱的數據。
ready()
如果服務端已經[設置狀態為ready](#publish_ready),將會返回 True。一個反應式數據源。
如果你在[`Tracker.autorun`](#tracker_autorun)里調用`Meteor.subscribe`, 當運算返回時,訂閱將被自動取消(所以如果合適的話,一個新的訂閱會被創建), 意味著你不能夠在來自`Tracker.autorun`里的訂閱中調用`stop`。