2016-03-27 1 views
3

Я реализую компонент Vaadin на основе JavaScript, который должен будет отображать и обновлять относительно большой набор данных. Я делаю это, расширяя AbstractJavaScriptComponent.Изменения частичного состояния для Vaadin's AbstractJavascriptComponent

Я стараюсь, чтобы JS-сторона была как можно более «тупой», делегируя взаимодействие пользователя с сервером с помощью RPC и обновляя общее состояние. Затем вызывается функция обертки соединителя JS onStateChange с новым состоянием, что заставляет DOM обновляться соответствующим образом.

У меня есть 2 проблемы:

  1. Я не хочу, чтобы передать весь набор данных, каждый раз, когда небольшая часть обновляется.
  2. Я не хочу полностью перестраивать пользовательский интерфейс каждый раз.

Я могу решить вторую проблему, сохранив предыдущее состояние и сравнив его части, чтобы узнать, что изменилось и только внести необходимые изменения DOM. Но это все еще оставляет первую проблему.

Должен ли я прекратить использование механизма общего состояния Vaadin и вместо этого использовать RPC для передачи изменений в состояние?

Update: Я делал некоторые испытания, и это, безусловно, представляется, что общий государственный механизм Vaadin является ужасен с точки зрения эффективности:

Всякий раз, когда компонент вызывает getState() для того, чтобы обновить некоторые свойства в (или даже не обновляя ничего), передается объект состояния . Единственный способ избежать этого, насколько я вижу, - не использовать механизм общего состояния и вместо этого использовать вызовы RPC для передачи клиенту определенных изменений состояния.

Есть некоторые проблемы с подходом RPC, которые необходимо будет устранить, например: если вы меняете значение несколько раз за один цикл запроса/ответа, вы не хотите делать вызов RPC несколько раз. Вместо этого вы хотите, чтобы только последнее значение отправлялось так же, как механизм общего состояния, только отправляет конечное состояние в ответ. Вы можете хранить грязные флажки для каждой части состояния, которую вы хотите отправить отдельно (или просто сохранить копию предыдущего состояния и сравнить), но затем вам нужно как-то вызвать вызов RPC в конце обработки запроса. Как это может быть сделано?

Любые идеи по этому поводу приветствуются!

Обновление 2:

Vaadin 8 фиксирует корневой выпуск: он посылает только измененные свойства состояния. Кроме того, он больше не вызывает onStateChange() на JS-коннекторе, когда только выполняет вызов RPC (и не меняет состояние).

ответ

2

OP правильный, заявив, что синхронизация общего состояния неэффективна для компонентов, основанных на AbstractJavaScriptComponent. Весь объект состояния сериализуется и становится доступным для метода onStateChange соединителя Javascript всякий раз, когда соединитель помечен как грязный. Другие компоненты, отличные от javascript, обрабатывают обновления состояния более разумно, только отправляя изменения. Точное место в коде, где это происходит, строка 97 в com.vaadin.server.LegacyCommunicationManager.java

boolean supportsDiffState = !JavaScriptConnectorState.class 
      .isAssignableFrom(stateType); 

Я не уверен, почему обновление состояния обрабатывается по-разному для AbstractJavaScriptComponent -На компонентов. Возможно, это упростить javascript-коннектор и удалить необходимость создания полного объекта состояния из дельт. Было бы здорово, если бы это можно было решить в будущей версии.

Как вы предлагаете, вы можете полностью отказаться от JavaScriptComponentState и полагаться на server-> client RPC для обновлений. Храните грязные флажки в своем серверном компоненте или сравните старое состояние и новое состояние любым необходимым вам механизмом.

Чтобы объединить изменения и отправить только один вызов RPC для каждого изменения, вы можете переопределить beforeClientResponse(boolean initial) в своем серверном компоненте. Это вызвано непосредственно перед отправкой ответа клиенту, и это ваш шанс добавить набор вызовов RPC для обновления клиентского компонента.

В качестве альтернативы, вы можете переопределить encodeState, где у вас есть свободное владение, чтобы отправлять именно те JSON, которые вам нравятся. Вы можете добавить список изменений в базовый объект JSON, возвращенный super.encodeSate. Ваш javascript-коннектор может интерпретироваться соответствующим образом в своем методе onStateChange.

Отредактировано для добавления: вызывающий getState() в своем серверном компоненте будет отмечать разъем как грязный. Если вы хотите получить состояние, не отметив его как грязное, используйте вместо этого getState(false).

+0

Точно ответ, который я искал. Когда «обманывать», не отправляя полное состояние при переопределении encodeState, существуют ли какие-либо оговорки относительно отсоединения и прикрепления? Например, если полное состояние должно быть отправлено после отсоединения и повторного подключения? – herman

+0

К сожалению, на этот раз я должен отказаться от ответа. Причина в том, что невозможно предотвратить передачу полного состояния (и вызываемой функции 'onStateChange()' JS), поскольку 'AbstractComponent # beforeClientResponse (логический начальный)' вызывает 'getState()' повторно, отмечая соединитель как грязный. Конечно, мы можем переопределить, но я уверен, что код существует по какой-то причине. ИМО это ошибка Ваадина. – herman

+0

Я подал [этот билет] (https://dev.vaadin.com/ticket/19828) на свой трекер. Мне нужно найти способ обойти это. – herman

-1

Совместное состояние Vaadin работает точно так же, как вы хотите из коробки: когда компонент добавляется в DOM в первый раз, все общее состояние передается от сервера к клиенту, так что можно отображать компонент. После этого переносятся только изменения. Например, один изменяет заголовок видимого компонента, вызывая component.setCaption("new caption"), Vaadin передает этот новый текст заголовка клиенту и «объединяет» его с экземпляром общего состояния клиента на стороне клиента.

+0

Как это работает при изменении вложенных свойств? Например, если у моего объекта состояния есть список лиц, и один из адресов лиц изменился? Что передано: весь список, один человек или один адрес? – herman

+0

Извините, но вам нужно понизить. Я протестировал это: компонент вызывает 'getState()', чтобы обновить любое значение (также в 'setCaption()'), что заставляет коннектор быть помечен как грязный, а затем я вижу, что все состояние передается, даже если одно значение изменилось. На самом деле, даже если ничего не изменилось (вызывается только 'getState()'). – herman

+0

Герман прав, заявив, что обнаружение изменений не реализовано для компонентов на основе AbstractJavaScriptComponent. См. Мой ответ для подробностей. –

0

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

https://github.com/emuanalytics/vaadin-enhancedjavascript

Решение обманчиво проста: в основном повторного включения вычисления состояния разницу в обход этой строки кода в com.vaadin.server.LegacyCommunicationManager.java:

boolean supportsDiffState = !JavaScriptConnectorState.class 
     .isAssignableFrom(stateType); 

Реализация решения осложняется тем фактом, что Классы Vaadin не просто расширены, поэтому мне пришлось копировать и повторно реализовывать 6 классов.

+0

Спасибо, я взгляните, когда у меня будет время. Я также заметил, что классы Ваадина трудно продлить из-за 'private' /' final'. Я все же считаю, что ненужные вызовы функции 'onStateChange()' оболочки коннектора JS необходимо фиксировать, даже если включен алгоритм diff. Прямо сейчас я работал над этой частью проблемы, добавив свойство 'version' в состояние и увеличивая это только при фактическом изменении некоторых свойств состояния, а затем сравнивая это с предыдущим значением в оболочке коннектора. – herman

+0

Btw было бы предпочтительнее использовать этот аддон вместо того, чтобы вообще не использовать общее состояние и просто явным образом вызывать методы JS (используя 'callFunction') для передачи определенных изменений состояния (используя объединение в' beforeClientResponse', как вы описали в другом ответе)? Таким образом, клиенту также не нужно определять, что изменилось, осмотрев дельты. – herman

+0

С помощью этого компонента onStateChange() НЕ запускается при использовании функции callFunction() для выполнения server-> client RPC сервера. Вы можете использовать общее состояние или RPC без каких-либо раздутых полезных нагрузок. В этом отношении использование этого компонента аналогично использованию «родного» компонента на основе vaadin/GWT. Использовать разделяемое состояние или RPC (или смесь обоих) зависит от вас и будет зависеть от того, какой API-интерфейс подвергается компоненту Javascript, который вы обертываете. Например, если API - это плоский, основанный на процедурах API, тогда RPC, вероятно, более подходит. Я использую его для упаковки MapboxGL.js и использую микс. –

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

  • Нет связанных вопросов^_^