@shilman “Meteor.Error” is a misnomer in the first place because it only exists for DDP as far as I can tell, so it should be called “DDP.Error” or “DDP.ClientError”. That said, I’d prefer to generalize more than that because I think the idea of a “standards spec” for throwing client-safe errors would be useful for many different frameworks beyond Meteor. I think the simplest and most generic way to “spec” this idea is a boolean prop clientSafe: true on any Error instance that is thrown.
My proposal for a standard spec would be something like this:
“When an Error is thrown while executing code as part of an HTTP or Websocket request, catch and examine the Error instance. If error.clientSafe is exactly true, then error.name, error.message, error.error, error.reason, and error.details may all be assumed to be safe to include in the response sent to the requesting client. Alternatively, if error.sanitizedError is an Error instance, then error.sanitizedError.name, error.sanitizedError.message, error.sanitizedError.error, error.sanitizedError.reason, and error.sanitizedError.details may all be assumed to be safe to include in the response sent to the requesting client. The error stack should never be sent.”
To follow this spec within Meteor/DDP, I think we only need to add an || error.clientSafe === true to the condition, and change the sanitizedError check to work when sanitizedError is any type of Error and not just Meteor.Error.
Also, @rlivingston we can add a custom error function, too, since that will likely be necessary in the short term until everyone can get onto a Meteor version where things work out of the box.
That makes sense. I’ve documented your proposal as a github issue, and am happy to make the code changes, add unit tests, update documentation, and whatever else is required to make this happen:
@aldeed@sashko please advise and feel free to comment on the issue, assign to me, etc. or I can create a PR and we continue the conversation there.
There’s still no mention of promises in guide other than in context of npm packages, is the expectation then to introduce dependencies in face of a solid choice (official) or just use wrapasync which apparently is a package for callback hell.
So async function evaluates as a promise (just “return 1” still makes it a promise), so, so long as method is appended with async then it becomes a promise.
No. It would not be possible to return a Promise to the client anyway - how would a client resolve a Promise made by the server?
However, there’s nothing stopping you from defining a Promise wrapper for the call. There is currently a “gap” with client-side method calls, in that they are not Promisified when the non-callback form is used. Although, there was at one time a PR which almost made it into Meteor core.
well await or then expects resolved promise, afaik promise is an object, so it’s not beyond impossible to send promise object (that has resolved status).
How do you return a value to the client when using the advanced methods? If I return a value in the run function it the result in the call is undefined.
I’ve been working with/learning what this guide calls “advanced” Meteor methods. It really helps me out with better unit testing, but I’m not able to get a returned value from client calling code when my ‘run’ function returns something. Within the client callback, both err and res are always undefined. I notice that here in the docs, only stubs for mongo operations are discussed and those appear to happen implicitly when returnStubValue is set to true. But what about when I just want the server to find/calculate something and return it to the client? I haven’t turned up many answers via google searches either.
The rest of my advanced method code is IDENTICAL to what’s here in the documentation; most significantly, the definition of the call() method.
What I get back is that both err and res are undefined, and yes, there are documents in the db. As a matter of fact I even altered the run() code to return a literal (say, “return 12”), however, in the client code, res still comes back as undefined.
So it would seem we cannot return arbitrary values from advanced meteor methods like we could with conventional methods, or else I’m just not understanding some extra steps we would have to take in order to do that…? Whatever that is, it’s far from obvious, to me at least.