Promises play no role in this instance. The code would be as simple as follows:
Meteor.methods({
sendVerificationLink: () => {
if (!Meteor.userId()) {
throw new Meteor.Error("not-logged-in", "You are not logged in.");
}
const body = Meteor.user().services.email.verificationTokens[0].token;
Email.send({
SecureToken: "xxx",
To: "xxx@yopmail.com",
From: "xxx@gmail.com",
Subject: "This is the subject",
Body: body,
});
}
});
Note:
- it would make sense to check whether the object hierarchy
Meteor.user().services.email.verificationTokens[0].token
exists, because if it doesn’t, you’ll get a TypeError
. I would use lodash get
or Meteor._get
.
- if an error is thrown, just let it fly. Returning something like
{ isError: true, err }
is rather unusual. The convention is that the client callback should be invoked with an error, if there was one, rather than a result, which contains an error.
- what however would make sense in every method is a selective conversion of any error other than
Meteor.Error
to Meteor.Error
. For this purpose all of my methods are wrapped in a function with a try catch calling this function:
const rethrowAsMeteorError = error => {
if (error instanceof Meteor.Error) {
throw new Meteor.Error(error.error, error.reason, error.stack);
}
if (error instanceof Error) {
if (error.name === "ClientError") {
throw new Meteor.Error(error.error, {message: error.message, details: error.details}, error.stack);
}
throw new Meteor.Error(error.message, { actualErrorType: error.name }, error.stack);
}
if (error instanceof Object) {
throw new Meteor.Error(error.name, error.message, error.stack);
}
// the assumption is that "error" is of a primitive type, such as string or number, etc.
throw new Meteor.Error(error);
}
The problem at hand in Meteor is that if an error other than Meteor.Error
is thrown in method, all the client receives is a Meteor.Error
along the lines of “500 Server Error”, which is very inadequate.