Подтвердить что ты не робот

Meteor.methods возвращает undefined

Я использую метеорит 0.6.4.

Meteor.methods({
  random: function(top){
    var random = Math.floor((Math.random()*(top+1)));
    return random;
  }
});

Он возвращает undefined всякий раз, когда я выполняю

Meteor.call('random', 10);

Любые идеи, как я могу пройти мимо этого?

4b9b3361

Ответ 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, а их клиентские версии реализуют действительные заглушки (модификация минимального реплицированного подмножества локальной базы данных), которые могут выполняться синхронно.