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

Будущая композиция в Vert.x

Для тех, кто не знает, Vert.x – это управляемый событиями и неблокирующий инструментарий приложений. Это полигл… С тегами vertx, async, java.

Для тех, кто не знает, Vert.x – это управляемый событиями и неблокирующий инструментарий приложений. Это полиглот, поэтому вы можете использовать его с разными языками (как Java , Котлин , JavaScript , Заводной , Ruby или Scala ).

Что значит “не блокирующий”?

В синхронном программировании при вызове функции вызывающий должен подождать, пока не будет возвращен результат. Такое поведение может привести к проблемам с производительностью.

Часто “очевидным решением” кажется параллельное программирование , но иметь дело с общими ресурсами и потоками непросто, и тупики не за горами.

Объяснение того, как Vert.x гарантирует асинхронность через цикл событий концепция не входит в рамки этой статьи, но все, что вы, возможно, захотите узнать, раскрывается в замечательном Мягком руководстве по асинхронному программированию с помощью Vert.x .

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

asyncFunctionCall(result -> {
    doSometingWith(result);
})

Обычно большое “но” возникает при первом просмотре асинхронного фрагмента кода: Но… Мне нужен этот результат сейчас!

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

Фьючерсы против обратных вызовов

Существует два способа обработки асинхронных вызовов в Vert.x.

  • Передайте обратный вызов, который будет выполнен по завершении вызова.
  • Обработайте будущее, возвращенное из вызова функции/метода.

Обратный звонок

asyncComputation(asyncResult -> {
  if (asyncResult.succeeded()) {
    asyncResult.result()
    // do stuff with result
  } else {
    // handle failure
  }
})

Обратный вызов – это функция, передаваемая асинхронному методу, используемому для обработки результата ее вычисления. Это просто реализовать, но это имеет некоторые недостатки:

  • Модульное тестирование становится не таким уж быстрым
  • Ведет в ужасный Ад обратного вызова
  • Нужно написать еще больше кода.

Будущее

Future future = asyncComputation()

future.onSuccess(result -> {
  // do stuff
})

future.onFailure(cause -> {
  // handle failure
})

Чтобы избежать проблем, перечисленных для “способа обратного вызова”, Vert.x реализует концепцию под названием Будущее .

Будущее – это объект, который представляет собой результат действия, которое может произойти, а может и не произойти еще (ср. апидок ).

Как переключиться с обратного вызова, подобного вызову, на будущий

Рассмотрим пример обратного вызова, показанный выше. Мы хотим, чтобы будущий объект использовал преимущества шаблонов, описанных ниже, но асинхронное вычисление

Мы можем использовать Обещание . Согласно apidoc , он представляет собой доступную для записи сторону действия, которое может произойти, а может и не произойти. Это идеально соответствует вашим потребностям:

Promise promise = Promise.promise();
asyncComputation(asyncResult -> {
  if (asyncResult.succeeded()) {
    promise.complete(asyncResult.result());
  } else {
    promise.fail(asyncResult.cause());
  }
})
return promise.future()

Это оно. Мы превратили обратный звонок в будущее. API обещания дают нам способ сделать этот код более читабельным:

Promise promise = Promise.promise();
asyncComputation(promise::handle)
return promise.future()

Метод handle заботится о выполнении или невыполнении обещания, учитывая асинхронный результат.

Будущие модели

В объекте Future реализованы некоторые интересные шаблоны, которые эффективно помогают решать проблемы асинхронности:

  • Карта
  • Составить
  • Восстанавливать

Отображение будущего

Для тех из вас, кто знает о функции map , являющейся частью java Stream API, эта функция должна быть понятна немедленно.

Функция карты будущего принимает функцию, которая преобразует результат из одного типа в другой.

asyncComputation() // returns a Future
  .map(Integer::valueOf) // returns a Future
  .onSuccess(...)
  .onFailure(...)

Будущий состав

Метод compose аналогичен методу map , но используется, когда сопоставление само по себе является асинхронной операцией:

asyncComputation()
  .map(Integer::valueOf)
  .compose(id -> retrieveDataById(id)) // retrieveDataById returns a Future
  .onSuccess(...)
  .onFailure(...)

Будущее Восстановление

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

asyncComputation()
  .map(Integer::valueOf)
  .recover(cause -> Future.succeededFuture(0)) // when Integer::valueOf fails, the future could be recovered with a default value
  .compose(id -> retrieveDataById(id))
  .onSuccess(...)
  .onFailure(...)

Параллельная композиция

Для обработки нескольких будущих результатов одновременно необходим класс Составная функция , он предоставляет два статических заводских метода:

all возвращает будущее, которое завершится успешно, если все функции, переданные в качестве параметров, завершатся успешно, и завершится неудачно, если хотя бы одна из них завершится неудачно.

CompositeFuture.all(futureOne, futureTwo)
  .onSuccess(compositeResult ->
    // all futures succeeded
  )
  .onFailure(cause -> 
    // at least one failed
  );

любой возвращает будущее, которое завершится успешно, если какая-либо из функций, переданных в качестве параметров, завершится успешно, и завершится неудачно, если все завершатся неудачно.

CompositeFuture.any(futureOne, futureTwo)
  .onSuccess(compositeResult ->
    // at least one succeed
  )
  .onFailure(cause -> 
    // all failed
  );

Выводы

API будущей композиции в Vert.x представляет собой надежный способ написания простого и доступного асинхронного кода. Всегда помни:

  • никогда не создавайте исключений в асинхронном коде, вместо этого используйте failed future для обработки поведения при сбое.
  • в конце будущей композиции не забудьте указать будущие успехи ( об успехе ) и неудачи ( При сбое )

Оригинал: “https://dev.to/cherrychain/future-composition-in-vert-x-3gp8”