Рубрики
Без рубрики

Руководство по отложенному

Краткое и практическое руководство по отложенной библиотеке.

Автор оригинала: baeldung.

1. Обзор

JDeferred – это небольшая библиотека Java (также поддерживает Groovy ), используемая для реализации асинхронной топологии без написания шаблонного кода. Этот фреймворк вдохновлен обещанием Jquery/Ajax и шаблоном Отложенного объекта Android.

В этом уроке мы покажем, как использовать Deferred и его различные утилиты.

2. Зависимость Maven

Мы можем начать использовать Отложенный в любом приложении, добавив следующую зависимость в ваш pom.xml:


    org.jdeferred
    jdeferred-core
    1.2.6

Мы можем проверить последнюю версию Отложенного проекта в Центральном репозитории Maven .

3. Обещания

Давайте рассмотрим простой пример использования вызова подверженного ошибкам асинхронного REST | API вызова и выполним некоторую задачу на основе данных, возвращаемых API.

В простом jQuery описанный выше сценарий можно решить следующим образом:

$.ajax("/GetEmployees")
    .done(
        function() {
            alert( "success" );
        }
     )
    .fail(
        function() {
            alert( "error" );
        }
     )
    .always(
        function() {
            alert( "complete" );
        }
    );

Аналогично, Deferred поставляется с интерфейсами Promise и Deferred , которые регистрируют независимый от потока хук на соответствующем объекте, который запускает различные настраиваемые действия в зависимости от состояния этого объекта.

Здесь Отложенный действует как триггер, а Обещание действует как наблюдатель.

Мы можем легко создать этот тип асинхронного рабочего процесса:

Deferred deferred
  = new DeferredObject<>();
Promise promise = deferred.promise();

promise.done(result -> System.out.println("Job done"))
  .fail(rejection -> System.out.println("Job fail"))
  .progress(progress -> System.out.println("Job is in progress"))
  .always((state, result, rejection) -> 
    System.out.println("Job execution started"));

deferred.resolve("msg");
deferred.notify("notice");
deferred.reject("oops");

Здесь каждый метод имеет различную семантику:

  • done() – срабатывает только при успешном завершении ожидающих действий над отложенным объектом
  • fail() – срабатывает при возникновении некоторого исключения при выполнении ожидающих действий над отложенным объектом
  • progress() – срабатывает, как только выполняются отложенные действия над отложенным объектом
  • always() – срабатывает независимо от состояния отложенного объекта

По умолчанию статус отложенного объекта может быть ОЖИДАНИЕ/ОТКЛОНЕНО/РАЗРЕШЕНО . Мы можем проверить состояние с помощью метода deferred.state () .

Здесь следует отметить, что как только статус отложенного объекта изменяется на РАЗРЕШЕН, мы не можем выполнить отклонить операцию над этим объектом.

Аналогично, как только статус объекта будет изменен на ОТКЛОНЕН, мы не сможем выполнить разрешить или уведомить операцию над этим объектом. Любое нарушение приведет к исключению Illegalstateexception .

4. Фильтры

Перед получением конечного результата мы можем выполнить фильтрацию отложенного объекта с помощью DoneFilter .

Как только фильтрация будет завершена, мы получим потокобезопасный отложенный объект:

private static String modifiedMsg;

static String filter(String msg) {
    Deferred d = new DeferredObject<>();
    Promise p = d.promise();
    Promise filtered = p.then((result) > {
        modifiedMsg = "Hello "  result;
    });

    filtered.done(r > System.out.println("filtering done"));

    d.resolve(msg);
    return modifiedMsg;
}

5. Трубы

Подобно фильтру, Deferred предлагает интерфейс Done Pipe для выполнения сложных действий после фильтрации после разрешения отложенных ожидающих действий объекта.

public enum Result { 
    SUCCESS, FAILURE 
}; 

private static Result status; 

public static Result validate(int num) { 
    Deferred d = new DeferredObject<>(); 
    Promise p = d.promise(); 
    
    p.then((DonePipe) result > {
        public Deferred pipeDone(Integer result) {
            if (result < 90) {
                return new DeferredObject()
                  .resolve(result);
            } else {
                return new DeferredObject()
                  .reject(new Exception("Unacceptable value"));
            }
    }).done(r > status = Result.SUCCESS )
      .fail(r > status = Result.FAILURE );

    d.resolve(num);
    return status;
}

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

6. Отложенный менеджер

В сценарии реального времени нам нужно иметь дело с несколькими отложенными объектами, наблюдаемыми несколькими обещаниями. В этом сценарии довольно сложно управлять несколькими обещаниями по отдельности.

Вот почему JDeferred поставляется с Отложенным менеджером интерфейсом, который создает общий наблюдатель для всех обещаний. Следовательно, используя этого общего наблюдателя, мы можем создавать общие действия для всех обещаний:

Deferred deferred = new DeferredObject<>();
DeferredManager dm = new DefaultDeferredManager();
Promise p1 = deferred.promise(), 
  p2 = deferred.promise(), 
  p3 = deferred.promise();
dm.when(p1, p2, p3)
  .done(result -> ... )
  .fail(result -> ... );
deferred.resolve("Hello Baeldung");

Мы также можем назначить ExecutorService с пользовательским пулом потоков Отложенному менеджеру :

ExecutorService executor = Executors.newFixedThreadPool(10);
DeferredManager dm = new DefaultDeferredManager(executor);

На самом деле, мы можем полностью игнорировать использование Promise и можем напрямую определить Вызываемый интерфейс для выполнения задачи:

DeferredManager dm = new DefaultDeferredManager();
dm.when(() -> {
    // return something and raise an exception to interrupt the task
}).done(result -> ... )
  .fail(e -> ... );

7. Потокобезопасное Действие

Хотя большую часть времени нам приходится иметь дело с асинхронным рабочим процессом, иногда нам приходится ждать результатов всех параллельных задач.

В этом типе сценариев мы можем использовать только Object ‘s wait() метод для ожидания завершения всех отложенных задач :

DeferredManager dm = new DefaultDeferredManager();
Deferred deferred = new DeferredObject<>();
Promise p1 = deferred.promise();
Promise p = dm
  .when(p1)
  .done(result -> ... )
  .fail(result -> ... );

synchronized (p) {
    while (p.isPending()) {
        try {
            p.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

deferred.resolve("Hello Baeldung");

В качестве альтернативы мы можем использовать метод Promise interface wait Safely() для достижения того же самого.

try {
    p.waitSafely();
} catch (InterruptedException e) {
    e.printStackTrace();
}

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

8. Интеграция с Android

Отложенный может быть легко интегрирован с приложениями Android с помощью плагина Android Maven.

Для сборки APKLIB нам нужно добавить следующую зависимость в pom.xml :


    org.jdeferred
    jdeferred-android
    1.2.6
    apklib

Для НАШЕЙ сборки нам нужно добавить следующую зависимость в pom.xml :


    org.jdeferred
    jdeferred-android-aar
    1.2.6
    aar

9. Заключение

В этом уроке мы изучили Отложенный , и это разные утилиты.

Как всегда, полный исходный код доступен на GitHub .