Methods

Documentation of Meteor's Method (Remote Procedure Call) API.

Methods are remote functions that Meteor clients can invoke with Meteor.call.

Anywhere

Meteor.methods(methods)

import { Meteor } from 'meteor/meteor' (ddp-server/livedata_server.js, line 1589)

Defines functions that can be invoked over the network by clients.

Arguments

  • methodsObject
  • Dictionary whose keys are method names and values are functions.

Example:

  1. Meteor.methods({
  2. foo(arg1, arg2) {
  3. check(arg1, String);
  4. check(arg2, [Number]);
  5. // Do stuff...
  6. if (/* you want to throw an error */) {
  7. throw new Meteor.Error('pants-not-found', "Can't find my pants");
  8. }
  9. return 'some return value';
  10. },
  11. bar() {
  12. // Do other stuff...
  13. return 'baz';
  14. }
  15. });

Calling methods on the server defines functions that can be called remotely byclients. They should return an EJSON-able value or throw anexception. Inside your method invocation, this is bound to a methodinvocation object, which provides the following:

  • isSimulation: a boolean value, true if this invocation is a stub.
  • unblock: when called, allows the next method from this client tobegin running.
  • userId: the id of the current user.
  • setUserId: a function that associates the current client with a user.
  • connection: on the server, the connection this method call was received on.

Calling methods on the client defines stub functions associated withserver methods of the same name. You don’t have to define a stub foryour method if you don’t want to. In that case, method calls are justlike remote procedure calls in other systems, and you’ll have to waitfor the results from the server.

If you do define a stub, when a client invokes a server method it willalso run its stub in parallel. On the client, the return value of astub is ignored. Stubs are run for their side-effects: they areintended to simulate the result of what the server’s method will do,but without waiting for the round trip delay. If a stub throws anexception it will be logged to the console.

You use methods all the time, because the database mutators(insert, update, remove) are implementedas methods. When you call any of these functions on the client, you’re invokingtheir stub version that update the local cache, and sending the same writerequest to the server. When the server responds, the client updates the localcache with the writes that actually occurred on the server.

You don’t have to put all your method definitions into a single Meteor.methodscall; you may call it multiple times, as long as each method has a unique name.

If a client calls a method and is disconnected before it receives a response,it will re-call the method when it reconnects. This means that a client maycall a method multiple times when it only means to call it once. If thisbehavior is problematic for your method, consider attaching a unique IDto each method call on the client, and checking on the server whether a callwith this ID has already been made. Alternatively, you can useMeteor.apply with the noRetry option set to true.

Read more about methods and how to use them in the Methods article in the Meteor Guide.

Anywhere

this.userId

(ddp-common/method_invocation.js, line 38)

The id of the user that made this method call, or null if no user was logged in.

The user id is an arbitrary string — typically the id of the user recordin the database. You can set it with the setUserId function. If you’re usingthe Meteor accounts system then this is handled for you.

Server

this.setUserId(userId)

(ddp-common/method_invocation.js, line 87)

Set the logged in user.

Arguments

  • userIdString or null
  • The value that should be returned by userId on this connection.

Call this function to change the currently logged-in user on theconnection that made this method call. This simply sets the value ofuserId for future method calls received on this connection. Passnull to log out the connection.

If you are using the built-in Meteor accounts system then thisshould correspond to the _id field of a document in theMeteor.users collection.

setUserId is not retroactive. It affects the current method call andany future method calls on the connection. Any previous method calls onthis connection will still see the value of userId that was in effectwhen they started.

If you also want to change the logged-in user on the client, then after callingsetUserId on the server, call Meteor.connection.setUserId(userId) on theclient.

Anywhere

this.isSimulation

(ddp-common/method_invocation.js, line 20)

Access inside a method invocation. Boolean value, true if this invocation is a stub.

Server

this.unblock()

(ddp-common/method_invocation.js, line 75)

Call inside a method invocation. Allow subsequent method from this client to begin running in a new fiber.

On the server, methods from a given client run one at a time. The N+1thinvocation from a client won’t start until the Nth invocationreturns. However, you can change this by calling this.unblock. Thiswill allow the N+1th invocation to start running in a new fiber.

Server

this.connection

(ddp-common/method_invocation.js, line 53)

Access inside a method invocation. The connection that this method was received on. null if the method is not associated with a connection, eg. a server initiated method call. Calls to methods made from a server method which was in turn initiated from the client share the same connection.

Anywhere

new Meteor.Error(error, [reason], [details])

import { Meteor } from 'meteor/meteor' (meteor/errors.js, line 71)

This class represents a symbolic error thrown by a method.

Arguments

  • errorString
  • A string code uniquely identifying this kind of error.This string should be used by callers of the method to determine theappropriate action to take, instead of attempting to parse the reasonor details fields. For example:
  1. // on the server, pick a code unique to this error
  2. // the reason field should be a useful debug message
  3. throw new Meteor.Error("logged-out",
  4. "The user must be logged in to post a comment.");
  5. // on the client
  6. Meteor.call("methodName", function (error) {
  7. // identify the error
  8. if (error && error.error === "logged-out") {
  9. // show a nice error message
  10. Session.set("errorMessage", "Please log in to post a comment.");
  11. }
  12. });

For legacy reasons, some built-in Meteor functions such as check throwerrors with a number in this field.

  • reasonString
  • Optional. A short human-readable summary of theerror, like 'Not Found'.

  • detailsString

  • Optional. Additional information about the error,like a textual stack trace.

If you want to return an error from a method, throw an exception. Methods canthrow any kind of exception. But Meteor.Error is the only kind of error thata server will send to the client. If a method function throws a differentexception, then it will be mapped to a sanitized version on thewire. Specifically, if the sanitizedError field on the thrown error is set toa Meteor.Error, then that error will be sent to the client. Otherwise, if nosanitized version is available, the client getsMeteor.Error(500, 'Internal server error').

Anywhere

Meteor.call(name, [arg1, arg2…], [asyncCallback])

import { Meteor } from 'meteor/meteor' (ddp-client/common/livedata_connection.js, line 543)

Invokes a method passing any number of arguments.

Arguments

  • nameString
  • Name of method to invoke

  • arg1, arg2…EJSON-able Object

  • Optional method arguments

  • asyncCallbackFunction

  • 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).

This is how to invoke a method. It will run the method on the server. If astub is available, it will also run the stub on the client. (See alsoMeteor.apply, which is identical to Meteor.call except thatyou specify the parameters as an array instead of as separate arguments and youcan specify a few options controlling how the method is executed.)

If you include a callback function as the last argument (which can’t bean argument to the method, since functions aren’t serializable), themethod will run asynchronously: it will return nothing in particular andwill not throw an exception. When the method is complete (which may ormay not happen before Meteor.call returns), the callback will becalled with two arguments: error and result. If an error was thrown,then error will be the exception object. Otherwise, error will beundefined and the return value (possibly undefined) will be in result.

  1. // Asynchronous call
  2. Meteor.call('foo', 1, 2, (error, result) => { ... });

If you do not pass a callback on the server, the method invocation willblock until the method is complete. It will eventually return thereturn value of the method, or it will throw an exception if the methodthrew an exception. (Possibly mapped to 500 Server Error if theexception happened remotely and it was not a Meteor.Error exception.)

  1. // Synchronous call
  2. const result = Meteor.call('foo', 1, 2);

On the client, if you do not pass a callback and you are not inside astub, call will return undefined, and you will have no way to getthe return value of the method. That is because the client doesn’t havefibers, so there is not actually any way it can block on the remoteexecution of a method.

Finally, if you are inside a stub on the client and call anothermethod, the other method is not executed (no RPC is generated, nothing“real” happens). If that other method has a stub, that stub stands infor the method and is executed. The method call’s return value is thereturn value of the stub function. The client has no problem executinga stub synchronously, and that is why it’s okay for the client to usethe synchronous Meteor.call form from inside a method body, asdescribed earlier.

Meteor tracks the database writes performed by methods, both on the client andthe server, and does not invoke asyncCallback until all of the server’s writesreplace the stub’s writes in the local cache. In some cases, there can be a lagbetween the method’s return value being available and the writes being visible:for example, if another method still outstanding wrote to the same document, thelocal cache may not be up to date until the other method finishes as well. Ifyou want to process the method’s result as soon as it arrives from the server,even if the method’s writes are not available yet, you can specify anonResultReceived callback to Meteor.apply.

Anywhere

Meteor.apply(name, args, [options], [asyncCallback])

import { Meteor } from 'meteor/meteor' (ddp-client/common/livedata_connection.js, line 570)

Invoke a method passing an array of arguments.

Arguments

  • nameString
  • Name of method to invoke

  • argsArray of EJSON-able Objects

  • Method arguments

  • asyncCallbackFunction

  • Optional callback; same semantics as in Meteor.call.

Options

  • waitBoolean
  • (Client only) If true, don't send this method until all previous method calls have completed, and don't send any subsequent method calls until this one is completed.

  • onResultReceivedFunction

  • (Client only) This callback is invoked with the error or result of the method (just like asyncCallback) as soon as the error or result is available. The local cache may not yet reflect the writes performed by the method.

  • noRetryBoolean

  • (Client only) if true, don't send this method again on reload, simply call the callback an error with the error code 'invocation-failed'.

  • throwStubExceptionsBoolean

  • (Client only) If true, exceptions thrown by method stubs will be thrown instead of logged, and the method will not be invoked on the server.

  • returnStubValueBoolean

  • (Client only) If true then in cases where we would have otherwise discarded the stub's return value and returned undefined, instead we go ahead and return it. Specifically, this is any time other than when (a) we are already inside a stub or (b) we are in Node and no callback was provided. Currently we require this flag to be explicitly passed to reduce the likelihood that stub return values will be confused with server return values; we may improve this in future.

Meteor.apply is just like Meteor.call, except that the method arguments arepassed as an array rather than directly as arguments, and you can specifyoptions about how the client executes the method.

DDPRateLimiter

Customize rate limiting for methods and subscriptions.

By default, DDPRateLimiter is configured with a single rule. This rulelimits login attempts, new user creation, and password resets to 5 attemptsevery 10 seconds per connection. It can be removed by callingAccounts.removeDefaultRateLimit().

To use DDPRateLimiter for modifying the default rate-limiting rules,add the ddp-rate-limiter package to your project in your terminal:

  1. meteor add ddp-rate-limiter

Server

DDPRateLimiter.addRule(matcher, numRequests, timeInterval, callback)

import { DDPRateLimiter } from 'meteor/ddp-rate-limiter' (ddp-rate-limiter/ddp-rate-limiter.js, line 74)

Add a rule that matches against a stream of events describing method orsubscription attempts. Each event is an object with the followingproperties:

  • type: Either "method" or "subscription"
  • name: The name of the method or subscription being called
  • userId: The user ID attempting the method or subscription
  • connectionId: A string representing the user's DDP connection
  • clientAddress: The IP address of the user

Returns unique ruleId that can be passed to removeRule.

Arguments

  • matcherObject
  • Matchers specify which events are counted towards a rate limit. A matcher is an object that has a subset of the same properties as the event objects described above. Each value in a matcher object is one of the following:

    • a string: for the event to satisfy the matcher, this value must be equalto the value of the same property in the event object

    • a function: for the event to satisfy the matcher, the function mustevaluate to true when passed the value of the same propertyin the event object

Here's how events are counted: Each event that satisfies the matcher'sfilter is mapped to a bucket. Buckets are uniquely determined by theevent object's values for all properties present in both the matcher andevent objects.

  • numRequestsnumber
  • number of requests allowed per time interval.Default = 10.

  • timeIntervalnumber

  • time interval in milliseconds after whichrule's counters are reset. Default = 1000.

  • callbackFunction

  • function to be called after a rule is executed.

Custom rules can be added by calling DDPRateLimiter.addRule. The ratelimiter is called on every method and subscription invocation.

A rate limit is reached when a bucket has surpassed the rule’s predefinedcapactiy, at which point errors will be returned for that input until thebuckets are reset. Buckets are regularly reset after the end of a timeinterval.

Here’s example of defining a rule and adding it into the DDPRateLimiter:

  1. // Define a rule that matches login attempts by non-admin users.
  2. const loginRule = {
  3. userId(userId) {
  4. const user = Meteor.users.findOne(userId);
  5. return user && user.type !== 'admin';
  6. },
  7. type: 'method',
  8. name: 'login'
  9. };
  10. // Add the rule, allowing up to 5 messages every 1000 milliseconds.
  11. DDPRateLimiter.addRule(loginRule, 5, 1000);

Server

DDPRateLimiter.removeRule(id)

import { DDPRateLimiter } from 'meteor/ddp-rate-limiter' (ddp-rate-limiter/ddp-rate-limiter.js, line 86)

Removes the specified rule from the rate limiter. If rule hadhit a rate limit, that limit is removed as well.

Arguments

  • idstring
  • 'ruleId' returned from addRule

Server

DDPRateLimiter.setErrorMessage(message)

import { DDPRateLimiter } from 'meteor/ddp-rate-limiter' (ddp-rate-limiter/ddp-rate-limiter.js, line 32)

Set error message text when method or subscription rate limitexceeded.

Arguments

  • messagestring or Function
  • Functions are passed in an object with atimeToReset field that specifies the number of milliseconds until the nextmethod or subscription is allowed to run. The function must return a stringof the error message.