## Methods
Methods 是可以從客戶端調用的服務端函數。當你想做一些比`insert`, `update` 或是 `remove`復雜的事情,或是進行數據驗證,而`allow` 和 `deny`又無法滿足需求時,使用Methods非常合適。
Methods 可以返回值或是拋出錯誤。
### [Meteor.methods(methods)](#/basic/Meteor-methods)
Anywhere
Defines functions that can be invoked over the network by clients.
#### Arguments
methods Object
Dictionary whose keys are method names and values are functions.
在服務端調用`Meteor.methods`定義的函數可以在客戶端遠程調用。下面是一個method的例子,檢查參數,拋出錯誤:
```
// On the server
Meteor.methods({
commentOnPost: function (comment, postId) {
// Check argument types
check(comment, String);
check(postId, String);
if (! this.userId) {
throw new Meteor.Error("not-logged-in",
"Must be logged in to post a comment.");
}
// ... do stuff ...
return "something";
},
otherMethod: function () {
// ... do other stuff ...
}
});
```
[`check`](#check)函數用于確保method的參數是期望的[類型和結構](#matchpatterns)。
在method定義中,`this`綁定到一個method調用對象,method調用對象有幾個非常有用的屬性,包括:用于標識當前登錄用戶的`this.userId`。
你不用把所有的method定義都放到一個`Meteor.methods`里面;可以多次調用`Meteor.methods`,只要每個method的名字是唯一的。
### Latency Compensation
調用服務端的一個method會產生在網絡上一個來回的延遲。如果用戶由于這個延遲,需要等待一秒才能看到自己的評論顯示出來,會讓人非常不爽。這就是為什么Meteor有一個叫做 _method stubs_ 的功能。如果你在客戶端定義了一個和服務端同名的method,Meteor會運行它,嘗試預測服務端運行的結果。當服務端代碼執行完畢后,客戶端生成的預測結果會被實際結果替代。
[`insert`](#insert), [`update`](#update), 和[`remove`](#remove)的客戶端版本,都是以method方式實現,這樣在客戶端與數據庫進行交互的結果就會立即呈現。
### [Meteor.call(name, [arg1, arg2...], [asyncCallback])](#/basic/Meteor-call)
Anywhere
Invokes a method passing any number of arguments.
#### Arguments
name String
Name of method to invoke
arg1, arg2... [EJSON-able Object](#ejson)
Optional method arguments
asyncCallback Function
Optional callback, which is called asynchronously with the error or result after the method is complete. If not provided, the method runs synchronously if possible (see below).
用上面的方法來調用method。
### On the client
在客戶端調用的Method是異步執行,為了能夠獲取執行結果,你需要傳入一個回調函數。回調函數會收到兩個參數`error` 和 `result`。除非有異常拋出,否則`error`參數為`null`。當有異常拋出時,`error`參數是`Meteor.Error`的一個實例,同時`result`參數是undefined。
示例:調用`commentOnPost`method ,傳入兩個參數`comment` 和 `postId`:
```
// Asynchronous call with a callback on the client
Meteor.call('commentOnPost', comment, postId, function (error, result) {
if (error) {
// handle error
} else {
// examine result
}
});
```
作為方法調用的一部分,Meteor會跟蹤數據庫的更新,直到所有的更新都發送到客戶端之后才調用客戶端回調函數。
### On the server
在服務端,不用傳入回調函數 — 方法調用會阻塞直到執行完畢,返回結果或是拋出異常,就好像直接調用函數一樣:
```
// Synchronous call on the server with no callback
var result = Meteor.call('commentOnPost', comment, postId);
```
### [new Meteor.Error(error, [reason], [details])](#/basic/Meteor-Error)
Anywhere
This class represents a symbolic error thrown by a method.
#### Arguments
error String
A string code uniquely identifying this kind of error. This string should be used by callers of the method to determine the appropriate action to take, instead of attempting to parse the reason or details fields. For example:
```
// on the server, pick a code unique to this error
// the reason field should be a useful debug message
throw new Meteor.Error("logged-out",
"The user must be logged in to post a comment.");
// on the client
Meteor.call("methodName", function (error) {
// identify the error
if (error.error === "logged-out") {
// show a nice error message
Session.set("errorMessage", "Please log in to post a comment.");
}
});
```
For legacy reasons, some built-in Meteor functions such as `check` throw errors with a number in this field.
reason String
Optional. A short human-readable summary of the error, like 'Not Found'.
details String
Optional. Additional information about the error, like a textual stack trace.
如果想在method中返回一個錯誤,使用拋出異常。Method可以拋出任意類型的異常,但是只有`Meteor.Error`類型的錯誤會發送到客戶端。如果method拋出一個其它類型的異常,客戶端會收到`Meteor.Error(500, 'Internal server error')`。