Dealing with Meteor.Error and .wrapAsync() - best methods? -
please critique following methods of dealing errors in meteor:
a common problem meteor.wrapasync() method on meteor doesn't seem return actual error external api:
https://github.com/meteor/meteor/issues/2774
1. example using wrapasync()
i'm using simple api takes zipcode , returns location information:
/server/methods.js
var getlocationasync = function(zipcode, callback){ http.call("get", "http://api.zippopotam.us/us/" + zipcode, function(error, result) { callback(error,result); }); }; var getlocationwithwrap = meteor.wrapasync(getlocationasync); meteor.methods({ getlocationwithwrap: function(zipcode){ return getlocationwithwrap(zipcode); } }); if
meteor.call("getlocationwithwrap", "94043", function(error, result){ if(error){ console.log("here error: ", error) } else { console.log("success: ", result); } }) you proper response. if pass in invalid zipcode:
meteor.call("getlocationwithwrap", "940", function(error, result){ if(error){ console.log("here error: ", error) } else { console.log("success: ", result); } }) you generic internal server error [500] meaningless.
2. example using try/catch (see code comments)
meteor.methods({ getlocationwithwraptrycatch: function(zipcode){ try { return getlocationwithwrap(zipcode); } catch(error){ // error object contains 'stack' key // , value difficult use // error 404 rather 500 throw new meteor.error(error.stack); } } }); doing:
meteor.call("getlocationwithwraptrycatch", "940", function(error, result){ if(error){ console.log("here error: ", error) } else { console.log("success: ", result); } }) results in error object that's difficult parse.
3. example using @faceyspacey code
user @faceyspacey wrote function called makeasync (i've changed name makesync since code taking async function , allowing write in synchronous style).
what return object:
{error: error, data: data} the value of error actual error returned external api. if value of error null, value of data data returned external api.
/server/methods.js
meteor.makesync = function(fn, context) { return function (/* arguments */) { var self = context || this; var newargs = _.toarray(arguments); var callback; (var = newargs.length - 1; >= 0; --i) { var arg = newargs[i]; var type = typeof arg; if (type !== "undefined") { if (type === "function") { callback = arg; } break; } } if(!callback) { var fut = new future(); callback = function(error, data) { fut.return({error: error, data: data}); }; ++i; } newargs[i] = meteor.bindenvironment(callback); var result = fn.apply(self, newargs); return fut ? fut.wait() : result; }; }; var getlocationasync = function(zipcode, callback){ http.call("get", "http://api.zippopotam.us/us/" + zipcode, function(error, result) { callback(error,result); }); }; var getlocationwithmakesync = meteor.makesync(getlocationasync); meteor.methods({ getlocationwithmakesync: function(zipcode){ var result = getlocationwithmakesync(zipcode); if( result.error === null ){ return result.data; } else { throw new meteor.error(result.error.response.statuscode, "zipcode cannot found."); } }, }); now when
meteor.call("getlocationwithwrap", "94043", function(error, result){ if(error){ console.log("here error: ", error) } else { console.log("success: ", result); } }); you actual error returned external api or error-less result.
i third method better because have actual error object play external api. missing here? there better ways of handling async errors when using external apis?
@faceyspacey's way of doing best way in opinion. if @ source code wrapasync, it's similar (https://github.com/meteor/meteor/blob/832e6fe44f3635cae060415d6150c0105f2bf0f6/packages/meteor/helpers.js#l90). method used in several external packages.
Comments
Post a Comment