web-dev-qa-db-fra.com

Meteor: appeler une fonction asynchrone dans un Meteor.method et renvoyer le résultat

Je veux appeler une fonction asynchrone dans une méthode Meteor, puis renvoyer le résultat de cette fonction à Meteor.call.

(Comment est-ce possible?

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

Andrew Mao a raison. Meteor a maintenant Meteor.wrapAsync () pour ce genre de situation.

Voici le moyen le plus simple de facturer via stripe et également de passer une fonction de rappel:

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

        });
    }
});

J'ai trouvé cet article vraiment utile: Meteor: bon usage de Meteor.wrapAsync sur le serveur

19
jacksonkernion

Utilisez un avenir pour le faire. Comme ça:

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

Mise à jour :

Pour utiliser Future à partir de Meteor 0.5.1, vous devez exécuter le code suivant dans votre méthode Meteor.startup:

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

  // use Future here
});

Mise à jour 2 :

Pour utiliser Future à partir de Meteor 0.6, vous devez exécuter le code suivant dans votre méthode Meteor.startup:

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

  // use Future here
});

puis utilisez la méthode return au lieu de la méthode 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();
  }
});

Voir ce Gist .

36
Joscha

Les versions récentes de Meteor ont fourni la fonction Meteor._wrapAsync Non documentée qui transforme une fonction avec un rappel standard (err, res) En une fonction synchrone, ce qui signifie que la fibre actuelle cède jusqu'à ce que le rappel revienne, puis utilise Meteor. bindEnvironment pour vous assurer de conserver les variables d'environnement Meteor actuelles (telles que Meteor.userId()).

Une utilisation simple serait la suivante:

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

Vous devrez peut-être également utiliser function#bind Pour vous assurer que asyncFunc est appelé avec le bon contexte avant de l'encapsuler.

Pour plus d'informations, voir: https://www.eventedmind.com/tracks/feed-archive/meteor-meteor-wrapasync

26
Andrew Mao

Une autre option est ceci package qui atteint les mêmes objectifs.

meteor add meteorhacks:async

À partir du package README:

Async.wrap (fonction)

Enveloppez une fonction asynchrone et autorisez-la à s'exécuter à l'intérieur de Meteor sans rappel.

//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;
  }
});
5
FullStack