Ответ 1
Это совершенно нормальное поведение: вызов метода сервера в Meteor documented для асинхронности:
На клиенте, если вы не передадите обратный вызов, и вы не находитесь в заглушке, вызов вернет undefined, и у вас не будет способа получить возвращаемое значение метода.
Это означает, что когда вы запрашиваете метод Meteor.call
для удаленного выполнения на сервере, вызов локального метода не блокируется и немедленно возвращает undefined
.
Когда метод вызывается на сервере, он будет отправлять результат асинхронно клиенту, поэтому вы должны получить его с помощью шаблона обратного вызова:
Meteor.call("myMethod", arguments..., function(error, result){
if(error){
console.log(error.reason);
return;
}
// do something with result
});
Функция анонимного обратного вызова будет вызываться на клиенте, как только результат метода сервера будет отправлен обратно клиенту.
Есть еще одна тонкая особенность в Meteor, которая делает недействительным то, что я только что сказал: компенсация латентности и заглушки методов. В случае, если вызов метода сервера может быть правильно настроен на клиенте и, таким образом, выполнен сразу же без обращения к серверу, вы можете определить, что называется методом заглушки (или моделирования).
Общим примером использования этого поведения является немедленная вставка в локальную (подмножество подмножества клиентской репликации) некоторого содержимого пользователя, только что опубликованного (комментарий в статье блога, например): все необходимые данные и логика доступны, и это делает смысл имитировать вставку на сервер. Далее будет показано, что пользователь видит обновление веб-страницы, как только он отправил свой контент, даже если сервер еще не подтвердил эти изменения. (это пример того, как компенсация латентности реализована в Метеор).
Конечно, у сервера есть заключительные слова о том, что в конечном итоге вставляется в базу данных, это означает, что при выполнении двойного метода на стороне сервера его действия будут иметь приоритет и заменить то, что было вставлено в локальную базу данных.
Чтобы определить такой заглушку метода, вам просто нужно определить одно и то же имя метода сервера в клиентском коде.
Если объявление метода определено в общем коде (отправлено как клиенту, так и серверу), вы можете проверить, является ли вызов метода фактически симуляцией, проверяя свойство isSimulation
:
Meteor.methods({
myMethod: function(arguments...){
if(this.isSimulation){
// called from the client
}
}
});
ОБНОВЛЕНИЕ 26/11/2014: @steph643 прокомментировал, как последняя часть моего предыдущего ответа была фактически неправильной, вот исправление.
Обратите внимание, что вызовы метода сервера всегда могут вызываться с использованием синхронного синтаксиса, потому что серверная среда обеспечивает адекватный механизм блокировки (волокна).
Однако на клиенте, если вы вернете что-то из заглушки метода, его можно выполнить синхронно, только если вы находитесь внутри другого заглушки, и вы можете получить результат синхронно, т.е.
Meteor.methods({
intermediateMethod: function(){
return " WORLD";
},
method: function(){
var result = "HELLO";
result += intermediateResult;
var intermediateResult = Meteor.call("intermediateMethod");
return result;
}
});
Такое поведение немного странно, учитывая, что операции коллекции Mongo (insert/update/delete) реализованы как методы Meteor, а их клиентские версии реализуют действительные заглушки (модификация минимального реплицированного подмножества локальной базы данных), которые могут выполняться синхронно.