출처 : https://signal9.co.kr/tags/vert-x/
Handler<T>
콜백을 핸들러라고 명칭
vertx.setPeriodic(1000 * 5 , id -> Sytem.out.println("Fire!"));
Vert.x 프레임워크에서 비동기 동작을 하는 거의 모든 메소드는 위와 같은 기본을 형태 취한다.
메소드가 동작하기 위한 인자를 받고, 비동기로 동작하고, 마지막으로 해당 메소드의 비동기 동작의 결과(T)를 Handler 제너릭 타입 오브젝트로 받아 처리한다.
결과값의 형태를 한정 할 수 없기에 실행 메소드 시그니처를 제러릭타입 T로 지정
AsyncResult<T>
비동기 로직 상에서 알 수 없는 문제가 발생했을 경우 예외나 문제에 대한 정보를 확인하고싶을때
Vert.x에서는 AsyncResult<T>라는 비동기 처리 결과값을 전달하기 위한 인테페이스를 제공한다.
Handler<T>가 비동기 처리 완료시 동작을 정의하는 것이라면 AsyncResult<T>는 비동기 처리 상태와 결과값을 저장 장소 것이다.
즉 Handler의 제너릭타입 T를 한번 AsyncResult객체로 감싸서 처리하는 것이다. 실제 사용 시 Handler<AsyncResult<T>>형태로 사용하게 된다.
AsyncResult<T> 인터페이스에서 자주 사용되는 메소드
public interface AsyncResult<T> {
T result();
Throwable cause();
boolean succeeded();
}
- succeeded() : 로직이 성공했는지 체크하기 위해 사용.
- result() : 성공했을 경우에 로직의 결과 값을 반환.
- cause() : 예외가 발생할 경우 해당 예외 객체 정보.
private void callBackTestMethod(Handler<AsyncResult<String>> handler) {
String resultString = "this is test.";
Throwable th = null;
AsyncResult<String> asyncResult = new AsyncResult<String>() {
public String value = resultString;
public void complete(String value) {
this.value = value;
}
@Override
public String result() {
return value;
}
@Override
public Throwable cause() {
return th;
}
@Override
public boolean succeeded() {
return value != null ? true : false;
}
public boolean failed() {
return value != null ? false : true;
}
};
// prcess end.
handler.handle(asyncResult);
}
실제 프레임워크에서 구현된 이와 같은 형태의 메소드를 호출하는 코드는 아래와 같은 형태로 나올 수 있다.
callBackTestMethod(ar->{
if (ar.succeeded()) {
String result = ar.result();
System.out.println("result:" + result);
} else {
System.err.println("error:"+ar.cause().getMessage());
}
});
Future<T>
위 코드는 단순하게 성공/실패만 확인하기 위해서도 모든 내용을 구현해야 한다.
그래서 이런 번거로움을 해결하기 위해서 Vert.x는 Future 클래스를 제공한다.
public interface Future<T> extends AsyncResult<T>, Handler<AsyncResult<T>> {
/**
* Create a future that hasn't completed yet
*
* @param <T> the result type
* @return the future
* @deprecated instead use {@link Promise#promise()}
*/
@Deprecated
static <T> Future<T> future() {
return factory.future();
}
/**
* Created a succeeded future with the specified result.
*
* @param result the result
* @param <T> the result type
* @return the future
*/
static <T> Future<T> succeededFuture(T result) {
if (result == null) {
return factory.succeededFuture();
} else {
return factory.succeededFuture(result);
}
}
/**
* Like {@link #onComplete(Handler)}.
*/
@Fluent
Future<T> setHandler(Handler<AsyncResult<T>> handler);
/**
* Set the result. Any handler will be called, if there is one, and the future will be marked as completed.
*
* @param result the result
* @deprecated instead create a {@link Promise} and use {@link Promise#complete(Object)}
*/
@Deprecated
void complete(T result);
/**
* Set the failure. Any handler will be called, if there is one, and the future will be marked as completed.
*
* @param cause the failure cause
* @deprecated instead create a {@link Promise} and use {@link Promise#fail(Throwable)}
*/
@Deprecated
void fail(Throwable cause);
}
우선 Future 클래스는 AsyncResult<T>, Handler<AsyncResult<T>>를 상속하고 있다. 비동기 결과 및 상태이면서 비동기 결과를 처리하는 콜백 메소드 클래스이기도 한 것이다.
private void testProcess(Future<String> stringFuture) {
...
try {
stringFuture.complete("this is test.");
} catch (Exception ex) {
stringFuture.fail(ex);
}
}
private void caller() {
// 문자를 결과로 받는 객체 생성.
Future<String> stringFuture = Future.future();
// Future 객체를 받아서 내부 처리 결과를 저장함.
testProcess(stringFuture);
// testHander의 실행 결과를 처리할 수 있음.
stringFuture.setHandler(ar->{
if (ar.succeeded()) {
String result = ar.result();
System.out.println("result:" + result);
} else {
System.err.println("error:"+ar.cause().getMessage());
}
});
}
위 코드에서 보면 인터페이스 구현 부분이 전부 사라졌다. 그리고 코드 자체가 더 직관적으로 보임을 알 수 있다.
Promise<T>
public interface Promise<T> extends Handler<AsyncResult<T>> {
static <T> Promise<T> promise() {
return factory.promise();
}
void complete(T result);
void fail(Throwable cause);
Future<T> future();
...
}
기본 Handler<AsyncResult<T>>를 상속하고 있고, Future<T> future() 팩토리 메소드를 가지고 있다.
사용법은 Promise 인터페이스 객체를 생성해서 값을 쓰고 Future로 변환해서 값을 조회하는 방법으로 사용된다.
private Future<String> testPorcess() {
Promise<String> stringPromise = Promise.promise();
try {
stringPromise.complete("this is test.");
} catch (Exception ex) {
stringPromise.fail(ex);
}
return stringPromise.future();
}
private void caller() {
testPorcess().setHandler(ar->{
if (ar.succeeded()) {
String result = ar.result();
System.out.println("result:" + result);
} else {
System.err.println("error:"+ar.cause().getMessage());
}
});
}
Promise를 값을 저장하고 .future() 메소드를 호출해서 Future로 반환해서 처리하는 부분만 다르고 동일하다.
'STUDY > Vert.x' 카테고리의 다른 글
[Vert.x] setTimer , setPeriodic - 특정 시간 간격으로 작업하기 (0) | 2023.09.20 |
---|---|
[Vert.x] 이벤트버스(Event Bus)란? (0) | 2023.06.16 |
[Vert.x] 버텍스(Vert.x) 코드 분석 정리 (0) | 2023.06.16 |
[Vert.x] 버텍스(Vert.x)란? (0) | 2023.03.10 |