From the Meteor.wrapAsync
http://docs.meteor.com/#meteor_wrapasync you can see that you need to pass it a function and optionally a context, whereas on your two attempts you are passing the RESULT of calling the async version of Stripe.customers.create
.
Meteor.methods({
stripeCreateUser: function(options) {
// get a sync version of our API async func
var stripeCustomersCreateSync=Meteor.wrapAsync(Stripe.customers.create,Stripe.customers);
// call the sync version of our API func with the parameters from the method call
var result=stripeCustomersCreateSync({
description: 'Woot! A new customer!',
card: options.ccToken,
plan: options.pricingPlan
});
// do whatever you want with the result
console.log(result);
}
});
Meteor.wrapAsync
transforms an async function into a convenient synchronous-looking function which allows to write sequentially looking code. (underhood everything is still executed within the asynchronous Node.js event loop).
We need to pass to Meteor.wrapAsync
our API function (Stripe.customers.create
) along with the function context, ie this
inside the body of the API func, which in this case is Stripe.customers
.
EDIT :
How to retrieve errors ?
Traditional node style API functions usually take a callback as last argument that will get called ultimately when the required task is completed. This callback takes 2 arguments : error and data, either one will be null according to the result of the call.
How do we access the error object using the synchronous wrapped functions returned by Meteor.wrapAsync
?
We have to rely on using try/catch blocks, because in case of error, it will be thrown by the sync function instead of being passed as first argument of the async function callback.
try{
var result=syncFunction(params);
console.log("result :",result);
}
catch(error){
console.log("error",error);
}
// is the equivalent of :
asyncFunc(params,function(error,result){
if(error){
console.log("error",error);
return;
}
console.log("result :",result);
});
why doesn't Stripe need to be passed?
JavaScript has no "namespace" concept, so API developers use the common trick of defining a global object acting as API namespace, properties defined on this object are "sub-modules" of the API.
It means that Stripe.customers
is a submodule of the Stripe API exposing customers-related funcs, and as such these funcs this
context is Stripe.customers
, not Stripe
.
You can test it yourself by copy pasting this mocking code in your browser console :
Stripe={
customers:{
create:function(){
console.log(this==Stripe.customers);
}
}
};
And then calling the stub function in your browser console like this :
> Stripe.customers.create();
true