import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* @param <T>
* @author jiangyubin
*/
public class Promise<T> {
private final CompletableFuture<T> completableFuture;
public Promise(@NonNull Consumer<PromisePublisher<T>> consumer) {
this.completableFuture = new CompletableFuture<>();
consumer.accept(new PromisePublisher<T>(this.completableFuture));
}
private Promise(@NonNull CompletableFuture<T> completableFuture) {
this.completableFuture = completableFuture;
}
public static <R> Promise<R> empty() {
return new Promise<>(CompletableFuture.completedFuture(null));
}
public static <R> Promise<R> of(R r) {
return new Promise<>(CompletableFuture.completedFuture(r));
}
@SuppressWarnings("unchecked")
public static <R> Promise<List<R>> all(@NonNull List<Promise<R>> promises) {
CompletableFuture<R>[] futures = CollectionTools.map(promises, p -> p == null ? CompletableFuture.completedFuture(null) : p.completableFuture)
.toArray(new CompletableFuture[promises.size()]);
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(futures);
return new Promise<>(completableFuture.thenApply(v -> {
List<R> list = new ArrayList<>();
for (CompletableFuture<R> future : futures) {
try {
list.add(future.get());
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return list;
}));
}
public static <R> Promise<R> fail(Throwable e) {
return new Promise<>(p -> p.publishError(e));
}
public <R> Promise<R> then(@NonNull Function<? super T, ? extends R> fn) {
return new Promise<>(this.completableFuture.thenApply(fn));
}
public <R> Promise<R> thenCompose(@NonNull Function<? super T, ? extends Promise<R>> fn) {
return new Promise<>(publisher -> {
this.then(t -> {
try {
AssertTools.notNull(fn.apply(t), () -> new NullPointerException("函数:" + fn.getClass() + " 执行完成之后返回了null")).then(r -> {
publisher.publish(r);
return null;
}).peekError(throwable -> {
publisher.publishError(throwable);
});
} catch (Exception e) {
publisher.publishError(e);
}
return null;
}).peekError(throwable -> {
publisher.publishError(throwable);
});
});
}
public Promise<T> catchError(@NonNull Function<Throwable, T> fn) {
return new Promise<>(this.completableFuture.exceptionally(throwable -> {
return fn.apply(throwable.getCause());
}));
}
public Promise<T> catchErrorCompose(@NonNull Function<Throwable, Promise<T>> fn) {
return new Promise<T>(publisher -> {
this.then(t -> {
publisher.publish(t);
return null;
}).catchError(throwable -> {
try {
AssertTools.notNull(fn.apply(throwable), () -> new NullPointerException("函数:" + fn.getClass() + " 执行完成之后返回了null")).then(t -> {
publisher.publish(t);
return null;
}).peekError(e -> {
publisher.publishError(e);
});
} catch (Exception e) {
publisher.publishError(e);
}
return null;
});
});
}
/**
* 接收错误信息,回调执行完成之后,错误仍会被发布
*
* @param consumer
* @return
*/
public Promise<T> peekError(@NonNull Consumer<Throwable> consumer) {
return new Promise<T>(publisher -> {
this.then(t -> {
publisher.publish(t);
return null;
}).catchError(e -> {
try {
consumer.accept(e);
publisher.publishError(e);
} catch (Exception ex) {
publisher.publishError(ex);
}
return null;
});
});
}
/**
* 接收错误信息,回调执行完成之后,返回回调的返回值
*
* @param consumer
* @return
*/
public Promise<T> acceptError(@NonNull Consumer<Throwable> consumer) {
return this.catchError(e -> {
consumer.accept(e);
return null;
});
}
public T sync() throws RuntimeException {
try {
return this.completableFuture.get();
} catch (RuntimeException e) {
throw e;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
throw new RuntimeException(cause);
}
}
}
Publisher类
import java.util.concurrent.CompletableFuture;
/**
* @param <T>
* @author jiangyubin
*/
public class PromisePublisher<T> {
private final CompletableFuture<T> completableFuture;
protected PromisePublisher(CompletableFuture<T> completableFuture) {
this.completableFuture = completableFuture;
}
public void publish(T value) {
this.completableFuture.complete(value);
}
public void publishError(Throwable e) {
this.completableFuture.completeExceptionally(e);
}
}