Метеор: вызов асинхронной функции внутри Meteor.method и возвращение результата
Я хочу вызвать асинхронную функцию внутри метода Meteor, а затем вернуть результат из этой функции в Meteor.call.
(Как) возможно?
Meteor.methods({
my_function: function(arg1, arg2) {
//Call other asynchronous function and return result or throw error
}
});
Ответы
Ответ 1
Эндрю Мао прав. Meteor теперь Meteor.wrapAsync() для такого рода ситуаций.
Здесь простейший способ выполнить заряд через полосу, а также передать функцию обратного вызова:
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
});
}
});
Я нашел это сообщение действительно полезным:
Метеор: правильное использование Meteor.wrapAsync на сервере
Ответ 2
Используйте это будущее. Вот так:
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();
}
});
Обновление
Чтобы использовать Будущее, начиная с Meteor 0.5.1, вы должны запустить следующий код в методе Meteor.startup:
Meteor.startup(function () {
var require = __meteor_bootstrap__.require
Future = require('fibers/future');
// use Future here
});
Обновление 2:
Чтобы использовать Future начиная с Meteor 0.6, вам нужно запустить следующий код в методе Meteor.startup:
Meteor.startup(function () {
Future = Npm.require('fibers/future');
// use Future here
});
а затем используйте метод 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();
}
});
См. этот метод.
Ответ 3
Последние версии Meteor предоставили недокументированную функцию Meteor._wrapAsync
, которая превращает функцию со стандартным обратным вызовом (err, res)
в синхронную функцию, что означает, что текущее волокно дает до возврата обратного вызова, а затем использует Meteor.bindEnvironment для обеспечения что вы сохраняете текущие переменные среды Метеор (например, Meteor.userId())
.
Простым использованием будет следующее:
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
}
});
Вам также может потребоваться использовать function#bind
, чтобы убедиться, что asyncFunc
вызывается с правильным контекстом перед его переносом.
Для получения дополнительной информации см. https://www.eventedmind.com/tracks/feed-archive/meteor-meteor-wrapasync
Ответ 4
Другим вариантом является пакет, который достигает аналогичных целей.
meteor add meteorhacks:async
Из пакета README:
Async.wrap(функция)
Оберните асинхронную функцию и разрешите ее запускать внутри 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;
}
});