Javascript Meteor:在 Meteor.method 中调用异步函数并返回结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12569712/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:44:08  来源:igfitidea点击:

Meteor: Calling an asynchronous function inside a Meteor.method and returning the result

javascriptmeteor

提问by Joseph Tura

I want to call an asynchronous function inside a Meteor method and then return the result from that function to Meteor.call.

我想在 Meteor 方法中调用一个异步函数,然后将该函数的结果返回给 Meteor.call。

(How) is that possible?

(如何)这可能吗?

Meteor.methods({
  my_function: function(arg1, arg2) {
    //Call other asynchronous function and return result or throw error
  }
});

采纳答案by Hymansonkernion

Andrew Mao is right. Meteor now has Meteor.wrapAsync()for this kind of situation.

安德鲁毛是对的。Meteor 现在有Meteor.wrapAsync()用于这种情况。

Here's the simplest way to do a charge via stripe and also pass a callback function:

这是通过条带进行充电并传递回调函数的最简单方法:

var stripe = StripeAPI("key");    
Meteor.methods({

    yourMethod: function(callArg) {

        var charge = Meteor.wrapAsync(stripe.charges.create, stripe.charges);
        charge({
            amount: amount,
            currency: "usd",
            //I passed the stripe token in callArg
            card: callArg.stripeToken,
        }, function(err, charge) {
            if (err && err.type === 'StripeCardError') {
              // The card has been declined
              throw new Meteor.Error("stripe-charge-error", err.message);
            }

            //Insert your 'on success' code here

        });
    }
});

I found this post really helpful: Meteor: Proper use of Meteor.wrapAsync on server

我发现这篇文章真的很有帮助: Meteor:在服务器上正确使用 Meteor.wrapAsync

回答by Joscha

Use a Future to do so. Like this:

使用 Future 来做到这一点。像这样:

Meteor.methods({
  my_function: function(arg1, arg2) {

    // Set up a future
    var fut = new Future();

    // This should work for any async method
    setTimeout(function() {

      // Return the results
      fut.ret(message + " (delayed for 3 seconds)");

    }, 3 * 1000);

    // Wait for async to finish before returning
    // the result
    return fut.wait();
  }
});

Update:

更新

To use Future starting from Meteor 0.5.1, you have to run the following code in your Meteor.startup method:

要从 Meteor 0.5.1 开始使用 Future,您必须在 Meteor.startup 方法中运行以下代码:

Meteor.startup(function () {
  var require = __meteor_bootstrap__.require
  Future = require('fibers/future');

  // use Future here
});

  Update 2:

  更新2

To use Future starting from Meteor 0.6, you have to run the following code in your Meteor.startup method:

要从 Meteor 0.6 开始使用 Future,您必须在 Meteor.startup 方法中运行以下代码:

Meteor.startup(function () {
  Future = Npm.require('fibers/future');

  // use Future here
});

and then use the returnmethod instead of the retmethod:

然后使用return方法而不是ret方法:

Meteor.methods({
  my_function: function(arg1, arg2) {

    // Set up a future
    var fut = new Future();

    // This should work for any async method
    setTimeout(function() {

      // Return the results
      fut['return'](message + " (delayed for 3 seconds)");

    }, 3 * 1000);

    // Wait for async to finish before returning
    // the result
    return fut.wait();
  }
});

See this gist.

看到这个要点

回答by Andrew Mao

Recent versions of Meteor have provided the undocumented Meteor._wrapAsyncfunction which turns a function with a standard (err, res)callback into a synchronous function, meaning that the current Fiber yields until the callback returns, and then uses Meteor.bindEnvironment to ensure that you retain the current Meteor environment variables (such as Meteor.userId()).

最新版本的 Meteor 提供了未公开的Meteor._wrapAsync函数,该函数将带有标准(err, res)回调的函数转换为同步函数,这意味着当前 Fiber 会产生直到回调返回,然后使用 Meteor.bindEnvironment 来确保您保留当前的 ​​Meteor 环境变量(比如Meteor.userId()).

A simple use would be as the following:

一个简单的用法如下:

asyncFunc = function(arg1, arg2, callback) {
  // callback has the form function (err, res) {}

};

Meteor.methods({
  "callFunc": function() {
     syncFunc = Meteor._wrapAsync(asyncFunc);

     res = syncFunc("foo", "bar"); // Errors will be thrown     
  }
});

You may also need to use function#bindto make sure that asyncFuncis called with the right context before wrapping it.

您可能还需要使用function#bind来确保asyncFunc在包装它之前使用正确的上下文调用它。

For more information see: https://www.eventedmind.com/tracks/feed-archive/meteor-meteor-wrapasync

有关更多信息,请参阅:https: //www.eventedmind.com/tracks/feed-archive/meteor-meteor-wrapasync

回答by FullStack

Another option is this packagewhich achieves the similar goals.

另一种选择是这个,它实现了类似的目标。

meteor add meteorhacks:async

From the package README:

从包自述文件:

Async.wrap(function)

异步包装(函数)

Wrap an asynchronous function and allow it to be run inside Meteor without callbacks.

包装一个异步函数并允许它在没有回调的情况下在 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;
  }
});