Очевидный способ в GWT/Java для ожидания нескольких асинхронных событий для окончания

Что лучший способ состоит в том, чтобы ожидать нескольких асинхронных функций обратного вызова для окончания в Java перед продолжением. Конкретно я использую GWT с AsyncCallback, но я думаю, что это - универсальная проблема. Вот то, что я имею теперь, но конечно существует более чистый путь...

    AjaxLoader.loadApi("books", "0", new Runnable(){
        public void run() {
            bookAPIAvailable = true;
            ready();
        }}, null);
    AjaxLoader.loadApi("search", "1", new Runnable(){
        public void run() {
            searchAPIAvailable = true;
            ready();
        }}, null);


    loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {
        public void onSuccess(LoginInfo result) {
            appLoaded  = true;
            ready();
        }
    });

private void ready() {
    if(bookAPIAvailable && searchAPIAvailable && appLoaded) {
                // Everything loaded
    }
}
39
задан Sripathi Krishnan 7 June 2010 в 21:08
поделиться

5 ответов

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

Если вы не можете и вам действительно нужен хак, используйте Timer для периодического опроса, все ли данные загружены. Код, который вы вставили выше, предполагает, что метод login() будет завершен последним - что неверно. Он может завершиться первым, и тогда ваше приложение будет находиться в неопределенном состоянии, что очень трудно отлаживать.

2
ответ дан 27 November 2019 в 02:45
поделиться

Лучший сценарий, как сказал Шри, это перепроектировать ваше приложение так, чтобы оно вызывало бэкенд только один раз за раз. Это позволит избежать подобного сценария и сохранить пропускную способность и время задержки. В веб-приложении это самый ценный ресурс.

Однако модель GWT RPC не очень-то помогает вам организовать все таким образом. Я сам столкнулся с этой проблемой. Моим решением была реализация таймера. Таймер будет опрашивать ваши результаты каждые X секунд, и когда все ожидаемые результаты будут получены, ваш поток выполнения может быть продолжен.

PollTimer расширяет Timer
{
 public PollTimer()
 {
 //Я установил опрос каждые полсекунды, но это может быть все, что вы захотите.
 //В идеале это будет только на стороне клиента, так что вы сможете делать это... 
 //более частым (в пределах разумного), не слишком беспокоясь о производительности
 scheduleRepeating(500);
 }
 public void run 
 {
 //проверяем, все ли ваши обратные вызовы были выполнены
 if (notFinished)
 return;

      //continue with execution flow
      ...
     }

}

Выполните вызовы RPC, затем создайте новый объект PollTimer. Это должно помочь.

Материал в java.util.concurrent не поддерживается GWT Emulation. Это не поможет вам в данном случае. Для всех намерений и целей, весь код, который вы делаете на стороне клиента, является однопоточным. Постарайтесь принять этот образ мыслей.

0
ответ дан 27 November 2019 в 02:45
поделиться

Как говорит @Epsen, Future - это, вероятно, то, что вам нужно. К сожалению, я не верю, что Future совместимы с GWT. Проект gwt-async-future претендует на то, чтобы привнести эту функциональность в GWT, хотя я никогда его не пробовал. Возможно, стоит взглянуть.

5
ответ дан 27 November 2019 в 02:45
поделиться

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

Обратные вызовы вызывают некоторое GwtEvent, используя HandlerManager. Класс, содержащий готовые методы, регистрируется в HandlerManager как EventHandler для событий, запускаемых методами обратного вызова, и хранит состояние (bookAPIAvailable, searchAPIAvailable, appLoaded).

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

Пример использования GWTEvent, HandlerManager и EventHandler смотрите в http://www.webspin.be/?p=5

1
ответ дан 27 November 2019 в 02:45
поделиться

В идеале, вы хотите сделать так, как говорили другие плакаты, и сделать как можно больше в одном асинхронном вызове. Иногда приходится выполнять несколько отдельных вызовов. Вот как:

Вы хотите выстроить цепочку вызовов async. Когда последний async завершается (вход в систему), все элементы загружаются.

    final AsyncCallback<LoginInfo> loginCallback = new AsyncCallback<LoginInfo>() {
        public void onSuccess(LoginInfo result) {
            //Everything loaded
            doSomethingNow();
        }
    };
    final Runnable searchRunnable = new Runnable() {
        public void run() {
            loginService.login(GWT.getHostPageBaseURL(), loginCallback);
        }
    };

    final Runnable booksRunnable = new Runnable() {
        public void run() {
            AjaxLoader.loadApi("search", "1", searchRunnable, null);
        }
    };

    //Kick off the chain of events
    AjaxLoader.loadApi("books", "0", booksRunnable, null);

Cheers,

--Russ

0
ответ дан 27 November 2019 в 02:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: