Как использовать методы Meteor внутри помощника шаблона

Как определить метод Метеор, который также можно вызвать в помощнике шаблона?

У меня есть два файла:

file: lib/test.js

Meteor.methods({
    viewTest : function (str) {
        return str;
    }
});

file: client/myView.js

Template.helloWorld.helpers({
    txt : function () {
        var str = Meteor.call('viewTest', 'Hello World.');
        return str;
    }
});

Когда я даю "str" нормальную строку, все работает нормально. Но в этом случае мой шаблон не получает никакой ценности. Я определил - для теста - в том же файле, где метод является нормальной функцией и попытался вызвать функцию. Ошибка, которую я получил, заключалась в том, что функция не существует. Поэтому я думаю, что Метеор пытается отобразить шаблон, прежде чем он узнает о методах, которые я определил для него. Но я думаю, что это немного необычно - не так ли?

Ответы

Ответ 1

Теперь есть новый способ сделать это (Meteor 0.9.3.1), который не загрязняет пространство имен Session

Template.helloWorld.helpers({
    txt: function () {
        return Template.instance().myAsyncValue.get();
    }
});

Template.helloWorld.created = function (){
    var self = this;
    self.myAsyncValue = new ReactiveVar("Waiting for response from server...");
    Meteor.call('getAsyncValue', function (err, asyncValue) {
        if (err)
            console.log(err);
        else 
            self.myAsyncValue.set(asyncValue);
    });
}

В обратном вызове "created" вы создаете новый экземпляр ReactiveVariable (см. docs) и присоединяете его к экземпляру шаблона.

Затем вы вызываете свой метод и когда срабатывает обратный вызов, вы присоединяете возвращаемое значение к реактивной переменной.

Затем вы можете настроить своего помощника, чтобы вернуть значение реактивной переменной (которая теперь привязана к экземпляру шаблона), и она будет повторно запускаться при возврате метода.

Но обратите внимание, что вам придется добавить пакет reactive-var для работы

$ meteor add reactive-var

Ответ 2

Сашко добавил аккуратный маленький пакет под названием meteor-reactive-method, чтобы решить эту проблему.

$ meteor add simple:reactive-method
Template.helloWorld.helpers({
  txt: function() {
    return ReactiveMethod.call('viewTest', 'Hello World.');
  }
});

Как я отмечаю в распространенных ошибках, помощники должны быть свободными от побочных эффектов, поэтому я буду использовать этот метод с осторожностью. Тем не менее, это действительно удобный ярлык для случаев, когда:

  • Помощник должен срабатывать только один раз (он не зависит от реактивного состояния).
  • Выбранный метод не мутирует базу данных.

Ответ 3

Вам нужно связать свое возвращаемое значение с переменной Session, поскольку запрос является асинхронным:

Template.helloWorld.helpers({
    txt : function () {
        return Session.get("txt") || "Loading";
    }
});

Template.helloWorld.created = function() {
    Meteor.call('viewTest', 'Hello World.', function(err, result) {
        Session.set("txt", result);
    });

}

Так что .rendered следует вызывать один раз, когда ваш шаблон загружается (по крайней мере, он должен быть с более новой версией Meteor.)

Значение будет вызываться и отображаться. В противном случае он сказал бы "Загрузка".

Ответ 4

Способы на стороне клиента асинхронны, и их возвращаемое значение всегда undefined. Чтобы получить фактическое значение, возвращаемое методом, вам необходимо предоставить обратный вызов:

Meteor.call('method', 'argument', function(error, result) {
    ....
});

Теперь нет простого способа использовать результат в вашем помощнике. Однако вы можете сохранить его в своем шаблоне в качестве объекта данных, а затем вернуть его в помощнике:

Template.template.created = function() {
    var self = this;
    self.data.elephantDep = new Deps.Dependency();
    self.data.elephant = '';
    Meteor.call('getElephant', 'greenOne', function(error, result) {
        self.data.elephant = result;
        self.data.elephantDep.changed();
    });
};

Template.template.showElephant = function() {
    this.elephantDep.depend();
    return this.elephant;
};

Ответ 5

Это ожидаемое поведение. Вы не используете methods, поскольку они предназначены.

Ваш код определяет метод сервера viewTest и соответствующий дескриптор метода на клиенте с тем же именем.

Meteor.call('viewTest', 'Hello World.'); удаленно вызывает viewTest на сервере и параллельно запускает заглушку на клиенте.

Что касается возвращаемого значения заглушки, см. документацию здесь, в частности:

На клиенте обратное значение заглушки игнорируется. Запуски запускаются для их побочных эффектов: они предназначены для имитации результата что будет делать серверный метод, но не дожидаясь раунда задержки отключения.

Что касается возвращаемого значения метода сервера, см. документацию здесь, в частности:

На клиенте, если вы не проходите обратный вызов, и вы не находитесь внутри заглушка, вызов вернет undefined, и у вас не будет способа получить возвращаемое значение метода. Это потому, что у клиента нет волокон, поэтому на самом деле он не может блокироваться на пульте дистанционного управления выполнение метода.