GWT: лучший способ выполнить начальный вызов RPC при запуске?

#gwt #rpc

#gwt #rpc

Вопрос:

Каков наилучший способ выполнить начальный вызов RPC при запуске с помощью GWT?

Я хотел бы получить данные конфигурации, которые динамически генерируются на стороне сервера, когда пользователь загружает страницу. но если я выполняю асинхронный RPC-вызов из браузера для извлечения данных, я иногда не получаю ответа до полной загрузки страницы, в результате чего страница не имеет доступа к этим данным конфигурации. (например, нет функции Thread.sleep())

Спасибо


благодаря ответу @Steve-J я нашел решение…

В основном идея заключается в следующем:

  • создайте новое событие StartupCompleted
  • запустите начальный вызов RPC в onModuleLoad()
  • в методе onSucess этого вызова RPC запустите событие StartupCompleted
  • в конце метода go() контроллера приложения вместо вставки действия по умолчанию в историю [ с помощью History.newItem(«default»); ] или для запуска текущего состояния истории, если вызывается через закладку [ с помощью History.fireCurrentHistoryState(); ],ничего не делайте
  • зарегистрируйте обработчик для нового события StartupCompleted на eventbus
  • когда запускается событие StartupCompleted, перехватите его и в это время вставьте действие по умолчанию в историю или запустите текущее состояние истории

et voila…

Начальный вызов RPC завершается перед выполнением чего-либо еще…

Есть ли что-то неправильное в этом подходе?

Обратите внимание, что, как было предложено @Tom-Miette, неплохо иметь простое сообщение «загрузка …», пока не будет получено событие StartupCompleted.

Ответ №1:

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

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

Обновление: из комментариев: «Но моя проблема в том, что пользователь может добавить страницу в закладки и перейти непосредственно к ней без какого-либо взаимодействия. Я могу оказаться в случае, когда я не получил результат вызова RPC, но где я генерирую страницу, которую он запросил. Даже если в этом поколении я попытаюсь проверить, получил ли я результат, я не могу сделать паузу, пока это не произойдет, прежде чем завершить генерацию страницы. «

А, понятно. Хорошо, у GWT есть решение для этого. Вы должны посмотреть на действия и места. Когда пользователь закладывает «страницу» в закладки, он действительно отмечает состояние приложения GWT. Когда он возвращается на эту «страницу», действие запускается и автоматически вызывает метод start() . Это ваша возможность получить данные с сервера и выполнить любые другие необходимые настройки. Как только у вас есть данные, ваш метод start() переходит к настройке так называемого «представления». С точки зрения пользователя, «страница» «загружена».

Комментарии:

1. Это. Пусть вашей первой точкой входа в модуль будет диспетчер RPC, а обратный вызов создаст ваш пользовательский интерфейс.

2. да, я делаю. Но моя проблема в том, что пользователь может добавить страницу в закладки и перейти непосредственно к ней без какого-либо взаимодействия. Я могу оказаться в случае, когда я не получил результат вызова RPC, но где я генерирую страницу, которую он запросил. Даже если в этом поколении я попытаюсь проверить, получил ли я результат, я не могу сделать паузу, пока это не произойдет, прежде чем завершить генерацию страницы.

3. Точка входа выполняется первой независимо от URL-адреса при запуске вашего модуля GWT. Можете ли вы дождаться обратного вызова перед настройкой пользовательского интерфейса и сохранить эти данные локально для доступа ко всем «страницам».

4. Как он добавляет страницу в закладки? Используете ли вы действия и места? Когда вы добавляете место в закладки, а затем возвращаетесь к нему, Activity Mapper всегда сначала выполняет метод запуска, при котором вы вызываете свой сервер для получения данных, а затем отображаете страницу на основе этих результатов. Я немного расширил свой ответ, основываясь на том, что вы сказали здесь.

5. @Steve-J На самом деле я использую предварительные сообщения и закладки «Действия и места». (используя History.newItem() и History.fireCurrentHistoryState(), как было задокументировано на веб-сайте GWT) К сожалению, я не могу найти способ приостановить поток до выполнения History.newItem(), соответствующего URL-адресу с закладкой, на случай, если мои данные не были загружены.

Ответ №2:

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

 <script type="text/javascript">
    var InitialState = {
    "userName" : "<%= userName %>",
    "emailAddress" : "<%= emailAddress %>",
    etc...
};
 

В вашем приложении GWT вы можете прочитать эти значения, используя класс GWT Dictionary

 Dictionary state = Dictionary.getDictionary("InitialState");
String userName = state.get("userName");
String emailAddress = state.get("emailAddress");
 

Комментарии:

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

Ответ №3:

Закройте свою HTML-страницу своего рода «загрузочным экраном»:

 <div 
id="loading"
style="
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background: black;
  color: white;"
>
  Loading...
</div>
 

и просто удалите его, когда RPC завершится успешно / неудачно:

 RootPanel.get("loading").getElement().removeFromParent();
 

Комментарии:

1. это интересный подход… однако это работает только для того, чтобы запретить пользователю что-либо делать, пока вы не получите результаты начального вызова RPC. Однако в моем случае пользователь может добавить URL-адрес в закладки, и конкретная страница будет «подготовлена» без необходимости пользователю что-либо делать. Таким образом, я все еще могу дойти до точки, когда начальный RPC не вернулся, но мне нужны данные для завершения подготовки страницы.

Ответ №4:

FWIW У меня было решение, которое включает приостановку EntryPoint.onModuleLoad() до тех пор, пока RPC не вернется.

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

Результатом стал собственный RPC-вызов GWT (без шаблона команд), который запускал внедрение зависимостей после успешного выполнения.

Фрагмент класса EntryPoint:

 @Override
public void onModuleLoad() {
    SessionInfoProvider.init(new Runnable() {
        @Override
        public void run() {
            // can now complete setup
            AppInjector injector = GWT.create(AppInjector.class);
            injector.bootstrap();
        }
    });
}
 

Фрагмент SessionInfoProvider:

 public class SessionInfoProvider implements Provider<SessionInfo> {
private static SessionInfo.Bean sessionInfo;

/**
 * Needs to be called before the module is used.
 */
public static void init(final Runnable onCompletion) {
    GreetingServiceAsync s = GWT.create(GreetingService.class);
    s.loadSessionInfo(new AsyncCallback<SessionInfo.Bean>() {
        @Override
        public void onFailure(Throwable caught) {
            GWT.log("Failed to retrieve Session Info");
        }

        @Override
        public void onSuccess(SessionInfo.Bean result) {
            GWT.log("Successfully retrieved session info bean.  Username:"   result.getUserName());
            sessionInfo = resu<
            onCompletion.run();
        }
    });
}

@Override
public SessionInfo get() {
    if (sessionInfo == null) throw illegalState("Session Info not ready.");
    return sessionInfo;
}
}