meteor:在服务器上正确使用Meteor.wrapAsync

背景

我正在尝试将条形支付整合到我的网站中。 我需要使用我的私人分条密钥创build一个分条用户。 我将这个密钥存储在我的服务器上,然后调用服务器方法来创build用户。 也许有另一种方法来完成这个? 这是条纹api(为方便起见,在下面复制): https : //stripe.com/docs/api/node#create_customer

//stripe api call var Stripe = StripeAPI('my_secret_key'); Stripe.customers.create({ description: 'Customer for test@example.com', card: "foobar" // obtained with Stripe.js }, function(err, customer) { // asynchronously called }); 

我的尝试和结果

我一直在使用不同的服务器代码相同的客户端代码。 所有尝试立即给客户端的console.log(…)未定义,但在服务器console.log(…)上给予适当的响应:

 //client Meteor.call('stripeCreateUser', options, function(err, result) { console.log(err, result); }); //server attempt 1 var Stripe = StripeAPI('my_secret_key'); Meteor.methods({ stripeCreateUser: function(options) { return Meteor.wrapAsync(Stripe.customers.create({ description: 'Woot! A new customer!', card: options.ccToken, plan: options.pricingPlan }, function (err, res) { console.log(res, err); return (res || err); })); } }); //server attempt 2 var Stripe = StripeAPI('my_secret_key'); Meteor.methods({ stripeCreateUser: function(options) { return Meteor.wrapAsync(Stripe.customers.create({ description: 'Woot! A new customer!', card: options.ccToken, plan: options.pricingPlan })); } }); 

我也尝试了没有Meteor.wrapAsync。

编辑 – 我也使用这个包: https : //atmospherejs.com/mrgalaxy/stripe

Meteor.wrapAsync http://docs.meteor.com/#meteor_wrapasync你可以看到你需要传递一个函数和可选的上下文,而在你的两次尝试中,你传递调用asynchronous版本的;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将一个asynchronous函数转换成一个方便的同步function,允许编写顺序的代码。 (底下的一切仍然在asynchronousNode.js事件循环内执行)。

我们需要传递给Meteor.wrapAsync我们的API函数( Stripe.customers.create )以及函数上下文,也就是在函数体内部,在这个例子中是Stripe.customers

编辑:

如何检索错误?

传统的节点风格的API函数通常将callback作为最后一个参数,最终在所需任务完成时被调用。 这个callback有两个参数:错误和数据,根据调用的结果,任何一个都是空的。

我们如何使用Meteor.wrapAsync返回的同步包装函数来访问错误对象?

我们不得不依赖于try / catch块,因为在错误的情况下,它将被sync函数抛出,而不是作为asynchronous函数callback的第一个parameter passing。

 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); }); 

为什么不需要通过条纹?

JavaScript没有“命名空间”的概念,因此API开发者使用定义一个作为API命名空间的全局对象的通用技巧,在这个对象上定义的属性是API的“子模块”。 这意味着Stripe.customers是Stripe API的子模块,暴露了客户相关的Stripe.customers ,因此这些Stripe.customers上下文是Stripe.customers而不是Stripe

您可以通过在浏览器控制台中粘贴这个模拟代码来自行testing:

 Stripe={ customers:{ create:function(){ console.log(this==Stripe.customers); } } }; 

然后在您的浏览器控制台中调用存根(stub)函数,如下所示:

 > Stripe.customers.create(); true 

另一个select是这个包达到类似的目标。

 meteor add meteorhacks:async 

从包装自述文件:

Async.wrap(function)

包装一个asynchronous函数,并允许它在没有callback的情况下在Meteor中运行。

 //declare a simple async function function delayedMessge(delay, message, callback) { setTimeout(function() { callback(null, message); }, delay); } //wrapping var wrappedDelayedMessage = Async.wrap(delayedMessge); //usage Meteor.methods({ 'delayedEcho': function(message) { var response = wrappedDelayedMessage(500, message); return response; } }); 

首先,感谢@saimeunt的回答,这让一些困难的概念变得清晰。 然而,我想要一个经典的asynchronouscallback(错误,结果)显示错误和客户端的结果,以便我可以在浏览器中提供信息性的消息。

我这样解决了它:

服务器代码:

 var Stripe = StripeAPI(STRIPE_SECRET_KEY); Meteor.methods({ createCust: Meteor.wrapAsync(Stripe.charges.create, Stripe.charges) }); 

客户代码:

 var stripeCallOptions = { description: 'Woot! A new customer!', card: ccToken, plan: pricingPlan }; Meteor.call('createCust', stripeCallOptions, function(error, result){ console.log('client error', error); console.log('client result', result); }); 

看起来很整齐。 然而,不幸的是,wrapAsync有一个开放的错误,(见https://github.com/meteor/meteor/issues/2774 ),因为它不能恢复到调用者的错误。 一个名为Faceyspacey的天才已经写了一个名为Meteor.makeAsync()的替代品,你会在我提到的错误页面上find它,然而它返回结果或者错误给'result'variables,而'error'variables没有定义。 现在我没问题了,至less我已经在适当的错误对象上挂钩了。

如果你使用makeAsync(),你需要像这样导入期货:

 Meteor.startup(function () { //this is so that our makeAsync function works Future = Npm.require('fibers/future'); }); 

既然你将需要差不多每个函数被包装在asynchronous你应该做的是使用这个包https://atmospherejs.com/copleykj/stripe-sync它预先包装WrapAsync所有条纹function,使您的生活更轻松,代码更清洁。