Я провел некоторое исследование различных вариантов такой ситуации, поскольку некоторые другие здесь, возможно, уже сталкивались с ней.
Вариант A — вложенные вызовы в клиенте
Первый и самый очевидный — это вложенные вызовы. Это означает вызов следующей функции после получения результата обратного вызова.
// level 1
Meteor.call('methodCall', param1, param2, param3, function (error, result) {
// level 2
if (error) console.log(error.reason);
Session.set("xyz",result);
Meteor.call('methodCall',result, param2, param3, function (error, result) {
// level 3...
if (error) console.log(error.reason);
console.log("result: "+result);
Session.set("cdf",result);
});
});
Плюсы: классический способ js, не требуется никаких причудливых новых концепций, серверные методы придерживаются простой логики, в то время как клиент умирает, выполняя сложную работу.
Минусы: некрасиво, может вызвать путаницу и иногда трудно отлаживать
Требуется: Template.autorun
или Tracker.autorun
для оперативного захвата изменений из Session
.
Вариант B — обернуть асинхронно
Многие, возможно, уже сочли этот метод лучшим выбором для структурирования асинхронного кода в синхронизирующий.
Волокна (и wrapAsync, использующий волокна) делают код только выглядящим синхронизированным, но характер выполнения остается асинхронным. Это работает так же, как работают Promises или как работают async/await.
Плюсы: мощный в единой среде.
Минусы: нельзя использовать с Meteor.call.
Требуется: волокно для запуска
Проблема с Meteor.call
Однако вы не можете легко вызвать метод Meteor, используя эту функцию. Рассмотрим следующий код
const param1 = "param1";
const param2 = "param2";
const param3 = "param3";
const asyncCall = Meteor.wrapAsync(Meteor.call);
const result1 = asyncCall("methodCall", param1, param2, param3);
// result1 will be undefined
Для дальнейшего объяснения я приведу документацию:
На клиенте, если вы не передадите обратный вызов и не находитесь внутри заглушки, call вернет неопределенное значение, и у вас не будет возможности получить возвращаемое значение метода. Это связано с тем, что у клиента нет волокон, поэтому на самом деле он не может заблокировать удаленное выполнение метода.
Резюме: Meteor.wrapAsync
нельзя использовать вместе с Meteor.call
.
Вариант C — объединение в один метод
Вместо того, чтобы пытаться создать синхронизированную последовательность вызовов метеора, вы также можете предоставить все параметры и логику одному серверному методу, который возвращает объект, который хранит все возвращаемые значения:
client.js
const param1 = "param1";
const param2 = "param2";
const param3 = "param3";
Meteor.call('methodCall', param1, param2, param3, function (err, result) {
const xyz = result.xyz;
const cdf = result.cdf;
});
сервер.js
function _methodCall(p1, p2, p3) {
// ...
return result;
}
Meteor.methods({
'methodCall'(p1, p2, p3) {
const result1 = _methodCall(p1, p2, p3);
const result2 = _methodCall(result1, p2, p3);
return {
xyz: result1,
cdf: result2,
}
}
})
Это создаст последовательное выполнение (следуя последовательной логике, которую вы указали в своем вопросе) и вернет все результаты в связанном объекте.
Плюсы: последовательность по желанию, один запрос — все результаты Минусы: один дополнительный метод для тестирования, может ввести тесную связь между методами, возвращаемые объекты могут стать большими и сложными для разбора для clinet Требования: хороший смысл для разработки методов
Если я найду другие варианты, я добавлю их в этот пост.
person
Jankapunkt
schedule
21.03.2018