#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 (без шаблона команд), который запускал внедрение зависимостей после успешного выполнения.
@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;
}
}