Meteor wrapAsync или bindEnvironment без стандартной подписи обратного вызова
Я пытаюсь позвонить createTableIfNotExists
в этом пакете npm, и делайте это синхронно в Meteor на стороне сервера. https://www.npmjs.com/package/azure-storage
Тем не менее, подпись обратного вызова имеет тип function(error, result, response)
вместо традиционного function(error,result)
,
1) из-за этого я не могу использовать Meteor.wrapAsync
и вместо этого придется использовать Meteor.bindEnvironment
2) Я называю "bindEnvironment", как показано ниже. Обратите внимание на обратный вызов с 3 аргументами. Это работает, но теперь я хотел бы извлечь return value
Вернемся к первоначальному методу (т.е. к оригинальному волокну).
Обратите внимание, что просто определяя addResult вне createTableService
не работает, потому что обратный вызов внутри bindEnvironment
работает асинхронно относительно внешнего кода... т.е. demoFunction()
возвращается до установки обратного вызова addResult
,
var demoFunction = function(){
var addResult = null;
var tableService = azure.createTableService(acctName, acctKey);
tableService.createTableIfNotExists(asTableName, Meteor.bindEnvironment(function(error,result,response){
if (error) {
throw new Meteor.Error(500, "table create error - " + asTableName + ": "+ error);
}
console.log(result);
if(result){
addResult = /*call to meteor method*/
return addResult;
}
}));
return addResult; //this is what I would like to do, but will always be null, as written.
}
Как я могу позвонить createTableIfNotExists
и еще вернусь addResult
вернуться к функции, которая называется demoFunction()
?
Спасибо!
1 ответ
Вы можете использовать Future
от fibers/future
( node-fiber), который представляет собой просто другой уровень абстракции волокон, так как это реализация async/await или реализация обещания. (Обратите внимание, что использование оптоволокна напрямую не рекомендуется).
Общий шаблон будущего
Как вы уже указали, вы можете решить эту проблему, также используя async/await или обещания.
Тем не менее, если вы хотите знать, как использовать Future
Например, вы можете следовать этому популярному шаблону, который я использую во многих моих приложениях.
Модель будущего с Meteor.bindEnvironment
В том числе bindEnvironment
в этот шаблон, и немного реструктурируя код, это выглядит следующим образом:
import Future from 'fibers/future';
Meteor.methods({
myMeteorMethod: function() {
// load Future
const myFuture = new Future();
// create bound callback, that uses the future
const boundCallback = Meteor.bindEnvironment(function (error,results){
if(error){
myFuture.throw(error);
}else{
myFuture.return(results);
}
});
// call the function and pass bound callback
SomeAsynchronousFunction("foo", boundCallback);
return myFuture.wait();
}
});
Применяется к примеру кода
Применение этой модификации шаблона к вашему коду может привести к чему-то вроде приведенного ниже кода. Обратите внимание, что я отделил обратный вызов от создания внутри функции просто из-за читабельности. Конечно, вы можете просто создать его внутри функциональной головки, как вы это обычно делаете.
import Future from 'fibers/future';
var demoFunction = function(){
// load Future
const myFuture = new Future();
// create bound callback, that uses the future
const boundCallback = Meteor.bindEnvironment(function (error, result, response) {
if (error) {
myFuture.throw(new Meteor.Error(500, "table create error - " + asTableName + ": "+ error));
}
// do whatever you need to do here
// with result and response...
if (result) {
myFuture.return(result);
}
});
var tableService = azure.createTableService(acctName, acctKey);
// pass the bound callback here
tableService.createTableIfNotExists(asTableName, boundCallback);
return myFuture.wait();
}