Сессия

Отступление 5.5

На данный момент переведено

В этой главе вы:

  • Познакомитесь с сессиями в Meteor
  • Узнаете о функции autorun
  • Поймете, как работает горячая замена кода
  • Meteor - это реактивный фреймворк. Если в вашем коде или в любых других данных появились какие-либо изменения, то они применятся немедленно, без необходимости что-либо перезагружать или обновлять.

    Мы уже видели этот механизм в действии, когда наши шаблоны обновлялись сразу после изменения данных и route.

    Мы постараемся подробнее разобрать и понять, как это работает в следующих главах, но сейчас, мы бы хотели подробнее остановиться на некоторых основных “реактивных” функциях, которые используются повсеместно.

    Сессия в Meteor (The Meteor Session)

    На данный момент текущее состояние приложения Microscope полностью отражается в адресе URL (и в базе данных).

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

    Сессия является глобальным и быстрым хранилищем данных. Под глобальным, подразумевается глобальный singleton объект: есть одна сессия, и она доступна отовсюду. Использование глобальных переменных считается дурным тоном, но сессия сама по себе рассматривается как глобальное хранилище данных и используется в различных частях приложения.

    Изменение сессии (Changing the Session)

    Сессия доступна отовсюду как Session. Чтобы установить какое-либо значение в сессии, необходимо сделать следующее:

     Session.set('pageTitle', 'A different title');
    
    Browser console

    Прочитать данные сессии можно, написав Session.get('mySessionProperty');. Это очень быстрое и удобное хранилище данных. Если вы напишете это в хелпер, то заметите, что вывод хелпера моментально меняется после изменения переменной сессии.

    Чтобы проверить это, добавим следующий код в текст шаблона “layout”:

    <header class="navbar">
      <div class="navbar-inner">
        <a class="brand" href="{{pathFor 'postsList'}}">{{pageTitle}}</a>
      </div>
    </header>
    
    client/views/application/layout.html
    Template.layout.helpers({
      pageTitle: function() { return Session.get('pageTitle'); }
    });
    
    client/views/application/layout.js

    Meteor автоматически обновится (как мы уже знаем, это называется “горячее обновление кода” или HCR) сохраняя переменные сессии, так что теперь мы увидим новый заголовок “A different title” в панели навигации. Если ничего не произошло, то просто попробуйте набрать предыдущую команду Session.set() снова.

    Более того, если мы изменим значение еще раз (снова набрав Session.set() в консоли браузера), то мы увидим новый заголовок:

     Session.set('pageTitle', 'A brand new title');
    
    Browser console

    Сессия доступна глобально, так что изменения могут быть внесены в любом месте приложения. Это дает нам больше возможностей, но также может и загнать в ловушку.

    Идентичные изменения (Identical Changes)

    Если вы записываете в переменную сессии (Session.set()) одно и тоже значение повторно, Meteor'у хватит ума, чтобы не запускать реактивные обновления и избежать ненужных вызовов функций.

    Введение в Autorun (Introducing Autorun)

    Мы уже встречали пример реактивного источника данных и видели его в действии внутри хелпера шаблона. Хоть некоторые места в Meteor (такие, как хелперы шаблонов) и являются реактивными, львиная доля всего приложения - все еще простой не реактивный JavaScript.

    Давайте предположим, что где-нибудь в нашем приложении у нас есть следующий фрагмент кода:

    helloWorld = function() {
      alert(Session.get('message'));
    }
    

    Не смотря на то, что мы обращаемся к переменной сессии, контекст, в котором к ней обращались, не реактивен: мы не будем видеть новые alert‘ы каждый раз после изменения переменной.

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

    Попробуйте выполнить в браузерной консоли следующее:

     Deps.autorun( function() { console.log('Value is: ' + Session.get('pageTitle')); } );
    Value is: A brand new title
    
    Browser console

    Как вы могли ожидать, блок кода, переданный в autorun, сработал один раз и вывел в консоль значение переменной. Теперь давайте попробуем изменить заголовок:

     Session.set('pageTitle', 'Yet another value');
    Value is: Yet another value
    
    Browser console

    Магия! Как только значение переменной сессии изменилось, autorun узнал об этом и выполнил весь свой код снова, выведя новое значение в консоль.

    Итак, возвращаясь к предыдущему примеру, если мы хотим показывать новый alert при каждом изменении переменной cессии, нам нужно лишь обернуть наш код в блок autorun.

    Deps.autorun(function() {
      alert(Session.get('message'));
    });
    

    Как мы только что видели, autorun'ы могут быть очень полезными для отслеживания реактивных источников данных и обязательного реагирования на них.

    Горячее обновление кода (Hot Code Reload)

    Пока мы разрабатывали наш Microscope, мы использовали одно из преимуществ Meteor, сберегающих время: горячее обновление кода (HCR). Всякий раз, когда мы сохраняем один из файлов исходников, Meteor замечает изменения и незаметно перезапускает работающий сервер Meteor, оповещая каждого клиента о необходимости обновить страницу.

    Это очень похоже на автоматическое обновление страниц, но есть одно важное отличие.

    Чтобы понять его, начнем изменять переменную сессии, которую мы использовали:

     Session.set('pageTitle', 'A brand new title');
     Session.get('pageTitle');
    'A brand new title'
    
    Browser console

    Если мы обновим страницу в браузере вручную, наши переменные сессии будут потеряны (точнее, они будут созданы заново). Но если мы спровоцируем выполнение горячего обновления кода (например, сохранив один из файлов исходников), страница будет обновлена, а переменные сессии останутся прежними. Попробуйте!

     Session.get('pageTitle');
    'A brand new title'
    
    Browser console

    Итак, если мы используем переменные сессии для хранения того, что делает пользователь, HRC будет полностью прозрачной для него, так как сохранит значения всех переменных сессии. Это позволяет нам загружать новую production-версию нашего Meteor-приложения, будучи уверенными в минимальных нарушениях работы клиента наших пользователей.

    Рассмотрим это чуть подробней. Если мы будем хранить все состояния в URL и в сессии, то мы сможем прозрачно менять запущенный код каждого клиента с минимальными потерями.

    Давайте теперь проверим, что получится, если мы обновим страницу вручную:

     Session.get('pageTitle');
    null
    
    Browser console

    Когда мы перезагрузили страницу, мы потеряли сессию. При HCR Meteor сохраняет сессию в local storage вашего браузера и загружает ее после обновления. Однако, при явной перезагрузке имеет смысл иное поведение: если пользователь обновляет страницу, как если бы он снова перешел по такому же URL, то данные должны быть сброшены к начальному состоянию, которое увидит любой пользователь, посетивший этот URL.

    Самое важное в этой главе:

    1. Всегда храните состояние пользователя в сессии или в URL, тогда HCR будет проходить с минимальными потерями.
    2. Любое состояние, которое вы хотите разделить между пользователями, храните внутри URL.