Proper Meteor error handling with async calls using Future

I am wondering how to properly handle errors with Meteor when using async methods. I have tried the following, but the error is being returned in the result parameter on the client callback instead of the error parameter.

Server code:

Future = Npm.require('fibers/future');

Meteor.methods({
    'myServerMethod': function(){
        var future = new Future();

        // URL to some remote API
        var url = UrlOfTheApiIWantToCall;

        HTTP.get(url, {//other params as a hash},
            function (error, result) {
                if (!error) {
                    future.return(result);
                } else {
                    future.return(error);
                }
            }
        );

        return future.wait();
    }
});

Client code:

Meteor.call('myServerMethod', function (error, result) {
    if(error){
        console.warn(error);
    }

    console.log('result', result);
});

As I was saying above, 'error' is always undefined on the client side event when the HTTP.get() on the server side returned an error. I also tried replacing future.return(error); with future.throw(error); on the server side, but this really throws an error on the server side. The client side error parameter then gets a 500 Server Error, although the error thrown on the server was a 401 Unauthorized error.

So, is it possible to use Fiber's Future properly so that the client callback receives the same error parameter as the server callback?

Upvotes: 1

Views: 2875

Answers (1)

Curtis
Curtis

Reputation: 681

According to the Meteor.Error docs at http://docs.meteor.com/#/full/meteor_error

Methods can throw any kind of exception. But Meteor.Error is the only kind of error that a server will send to the client. If a method function throws a different exception, then it will be mapped to a sanitized version on the wire. Specifically, if the sanitizedError field on the thrown error is set to a Meteor.Error, then that error will be sent to the client. Otherwise, if no sanitized version is available, the client gets Meteor.Error(500, 'Internal server error').

Which is why you are receiving the 500 Server Error on the client. If you want to preserve the error message and have it be sent to the client, you can do something like this:

Future = Npm.require('fibers/future');

Meteor.methods({
    'myServerMethod': function(){
        var future = new Future();

        // URL to some remote API
        var url = UrlOfTheApiIWantToCall;

        HTTP.get(url, {//other params as a hash},
            function (error, result) {
                if (!error) {
                    future.return(result);
                } else {
                    future.throw(error);
                }
            }
        );

        try {
            return future.wait();
        }
        catch(err) {
            // Replace this with whatever you want sent to the client.
            throw new Meteor.Error("http-error", err);
        }
    }
});

Upvotes: 4

Related Questions