Автоматическая подписка на Meteor.js после обратного вызова с сервера

Я пытаюсь использовать функцию автоматической подписки Meteor на клиенте, но иногда она работает, а иногда нет. Итак, вот случай:
Рабочая версия: у меня есть раскрывающийся список, заполненный каналами. Когда пользователь нажимает на канал, я устанавливаю переменную сеанса и начинаю загружать потоки:

Template.channelDropdown.events({
    "click #channelLink": function() {
        Session.set("currentChannel", this);
    }
});

html

 <ul class="dropdown-menu">
            {{#each channels}}
                <li>
                    <a id="channelLink" href="#">{{name}}</a>
                </li>
            {{/each}}
 </ul>

а также

Tracker.autorun(function() {
    Meteor.subscribe("threadsByChannel", Session.get("currentChannel"));
});

Meteor.publish("threadsByChannel", function (channel) {
    return threads.find({channel: channel});
});

и загрузка потоков:

"channelThreads": function() {
    return threads.find({channel: Session.get("currentChannel")}).fetch();
},

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

   Template.channelSearchBar.events({
"submit #joinChannelForm": function() {
    event.preventDefault();

    var channelName = $("#channelNameField").val();
    Meteor.call("getChannelByName", channelName, function(error, result) {
        if (error) {
            // TODO error handling
        } else {
            Session.set("currentChannel", result);
        }
    });
    $("#channelNameField").val("");
}
});

сервер:

'getChannelByName': function (channelName) {
    var channel = channels.findOne({name: channelName});
    if (channel) {
        return channel;
    } else {
        var newChannel = {
            name: channelName
        }
        return channels.insert(newChannel);
    }
}

html

<template name="channelSearchBar">
      <form id="joinChannelForm" class="navbar-form navbar-left" role="search">
       <div class="form-group">
         <input id="channelNameField" type="text" class="form-control" placeholder="Enter channel name">
       </div>
       <button type="submit" class="btn btn-default">Join</button>
    </form>
</template>

Теперь единственная разница в том, что переменная сеанса устанавливается в обратном вызове. Я почти уверен, что это проблема, поскольку это асинхронный вызов сервера, и почему-то потоки не заполняются клиентом по запросу. Когда я устанавливаю точку останова в функции загрузки потоков (threads.find () на клиенте), я вижу, что переменная сеанса установлена ​​правильно, но она просто ничего не возвращает. Также иногда он вызывается два раза (например, при работе в первом случае первый вызов ничего не возвращает, а затем второй вызов по какой-то причине возвращает реальные результаты. Так оно и должно работать?). Я только начинаю изучать метеор и пытаюсь понять, как все это работает. Был бы рад, если бы меня кто-нибудь объяснил или направил в нужное русло.

РЕДАКТИРОВАТЬ: Это очень странно. Я поставил точку останова в функции публикации, и, похоже, она работает нормально - точно так же, как и должна. Однако в нерабочем случае он просто ничего не возвращает прямо со стороны сервера, хотя и рабочая, и не рабочая ситуации предоставляют (по-видимому) точно такой же объект канала. Похоже, проблема связана с запросом mongodb.


person Koks Skirtumas    schedule 29.01.2015    source источник
comment
Можете ли вы опубликовать, как выглядит ваш раскрывающийся HTML-код, который равен #channelLink"?   -  person ajduke    schedule 29.01.2015
comment
Да я обновил вопрос. Выпадающая версия работает нормально, кстати.   -  person Koks Skirtumas    schedule 29.01.2015
comment
Можете ли вы показать код метода getChannelByName, а также указать, где он у вас (на стороне сервера или совместно используемый)?   -  person Jeremy S.    schedule 29.01.2015
comment
Да ок, отредактировал. Это довольно просто. Я думал, что meteor.call всегда вызывает метод на сервере. Так что да, это на сервере. И, как я уже сказал, канал возвращается и успешно устанавливается на сеанс в обратном вызове, тогда просто threads.find () ничего не находит.   -  person Koks Skirtumas    schedule 29.01.2015


Ответы (2)


Почему бы не удалить Meteor.call и не сделать все на стороне клиента? Подписка на автозапуске вроде бы в порядке, давайте попробуем с этим кодом, просто убедитесь, что у вас есть allow/deny разрешения в порядке.

 Template.channelSearchBar.events({
   "submit #joinChannelForm": function() {
     event.preventDefault();
     var channel = channels.findOne({name: channelName}),
       channelName = $("#channelNameField").val();   
         if (channel) {
          return channel;
        } else {
         var newChannel = {
         name: channelName
        }
       var chanelCreated = channels.insert(newChannel);
       Session.set("currentChannel", chanelCreated);
       $("#channelNameField").val("");
    }
}
});
person Ethaan    schedule 29.01.2015
comment
Я предполагаю, что это сработает, но я не хочу вводить разрешения / запретить разрешения и просто использую метеорные методы для связи с сервером, потому что я не уверен, что у меня достаточно опыта, чтобы сделать его безопасным, и я боюсь неподдерживаемого кода потом. Я хотел бы, чтобы это было просто. Я действительно не хочу менять этот подход в отношении первой проблемы, с которой я сталкиваюсь, и предпочитаю выяснить, как это работает и почему это работает именно так. - person Koks Skirtumas; 30.01.2015
comment
как вы говорите, кажется, что данные не готовы, когда вы их запрашиваете, давайте поместим подписку в waitOn ,? waitOn: function (вернуть Meteor.subscribe?) - person Ethaan; 30.01.2015
comment
Привет, спасибо за помощь. Я обновил вопрос с новой информацией от отладки. Что делает waitOn? - person Koks Skirtumas; 30.01.2015
comment
waitOn, как и имена, говорят, что он ждет данных от определенной подписки, и когда данные будут готовы, шаблон был визуализирован, поэтому кажется, что он вам нужен - person Ethaan; 30.01.2015
comment
Понятно. Похоже, что настоящая проблема заключалась не в ошибке публикации / подписки метеора, а из-за того, что запрос mongo каким-то образом не распознал объект канала ... - person Koks Skirtumas; 30.01.2015

ОК, похоже, настоящая проблема заключалась не в ошибке публикации / подписки метеора, а из-за запроса mongodb, который не распознавал объект канала. Проблема была решена изменением этого:

threads.find({channel: channel})

к этому:

threads.find({"channel.name": channel.name})

Я обнаружил, что запросы mongo заботятся о порядке параметров объекта, но на данный момент у канала был только один параметр (имя), поэтому я до сих пор не уверен, почему они не считались равными. Один канал был возвращен из запроса findOne, а другой - из find. Один из находок был распознан.

person Koks Skirtumas    schedule 30.01.2015