2016-06-16 2 views
1

Я работаю над проектом Meteor и хочу получить возвращаемое значение Meteor.call в помощниках шаблонов на стороне клиента. Во-первых, я просто устанавливаю переменную в функции обратного вызова и получаю значение переменной за пределами Meteor.call. Я узнал код после того, как Meteor.call не выполняется вообще. Затем я немного искал и использовал Session, он работает. Но я не совсем понимаю причину. Вот мой оригинальный код и измененный код. Может ли кто-нибудь объяснить мне немного? Благодаря!!Как понять асинхронный Meteor.call на стороне клиента

Оригинал неправильный код: HTML

<div id="text-result-main"> 
    <h2>{{title}}</h2> 
</div> 

JS

Template.texts.helpers({ 
    title: function(){ 
    var index = Router.current().params.index; 
    Meteor.call('getTitle', index,function(error, result){ 
     titles = result; 
    }); 
    console.log(titles); 
    return titles; 
}}); 

Коллекция text.js

Text = new Mongo.Collection("text"); 
Meteor.methods({ 
    'getTitle': function(myindex){ 
    return Text.findOne({index: myindex}).title; 
    }}); 

Рабочий код: JS

Template.texts.helpers({ 
title: function(){ 
     var index = Router.current().params.index; 
     Meteor.call('getTitle', index,function(error, result){ 
     Session.set("titles",result); 
     }); 
     console.log(Session.get("titles")); 
    return Session.get("titles"); 
}}); 

Обратите внимание, что я вообще не публиковал коллекцию текста клиенту, потому что он такой огромный. Каждый раз, когда я обновляю страницу при запуске неправильного кода, я не вижу содержимого «title» или не вижу его на консоли. Но когда я устанавливаю сеанс, он работает. Я действительно не понимаю, как это работает. Благодаря

+0

Если у вас возникли проблемы с асинхронным вызовом (который вы, я могу сказать) просто конвертировать 'Meteor.call' в synchrnous один. – Quirk

ответ

1

Существует два вопроса асинхронность и Реакционная

Это притворство

Meteor.call('getTitle', index,function(error, result){ 
    titles = result; 
}); 

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

Попробуйте его в консоли вашего браузера.

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

Вот график:

  • методов называется

  • Возврат пустое значение

  • Метод выполняется, устанавливая значение переменной

  • Если переменная является источник реактивной информации, шаблон повторно вычисляется. (в вашем случае сеанс является реактивным источником данных.)

Чтобы идти дальше

Я хотел бы использовать реактивный вар в этом случае, это очень близко от переменного сеанса, но объем ограничен в шаблон.

Хорошо читать на Reactive источника данных: http://richsilv.github.io/meteor/meteor-reactive-data-types/

0

Почему бы не использовать что-то вроде этого:

title: function(){ 
    var index = Router.current().params.index; 
    var a = Text.findOne({index: myindex}).title; 
    console.log(a); 
    return a; 

без методов

+0

Это правда, что без дополнительной информации вызов метода здесь не является обязательным. –

+0

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

+0

Попробуйте использовать частичный индекс на mongodb.Партильные индексы только индексируют документы в коллекции, которые соответствуют указанному выражению фильтра. Таким образом, вы будете публиковать только подмножество коллекции. – AGdev

1

Проблема заключается в том, что Meteor.call() асинхронный, когда в паре с обратным вызовом.

Поэтому, когда title() начинает выполнение, он не ждет вашего вызова Meteor.call(), чтобы вернуть результат (или, возможно, ошибку). Он продолжает выполнение. Это называется асинхронным исполнением.

Короче говоря, вы пытаетесь зарегистрировать значение для ключа titles, которого нет в Session (так как состояние вашего асинхронного вызова Meteor неизвестно на данный момент времени).

Попробуйте перевести оператор консоли в обратный вызов в паре с вашим Meteor.call(), и вы можете увидеть результат, как только он был успешно установлен в Session.


Обходной к вашей проблеме, чтобы сделать ваш Meteor.call() синхронно, как это:

Template.texts.helpers({ 
title: function(){ 
     var index = Router.current().params.index; 
     var result = Meteor.call('getTitle', index); // <--- this is synchronous code now 
     Session.set("titles",result); 
     console.log(Session.get("titles")); 
     return Session.get("titles"); 
}}); 

Удаление обратного вызова делает Meteor.call() себя синхронно.

Если вы не передадите обратный вызов на сервере, вызов метода будет заблокирован до завершения метода. Он в конечном итоге вернет возвращаемое значение метода, или оно выдаст исключение, если метод сделал исключение.

(от http://docs.meteor.com/api/methods.html#Meteor-call)

+0

Привет! Это действительно не работает в моем коде. Я могу использовать асинхронный вызов и устанавливать сеанс внутри него. – yiyizheliu

+0

Предлагаемые вами фрагменты кода. Клиентская сторона Сессии 'sets' и' gets' разрешены в Meteor IIRC. – Quirk

Смежные вопросы