我正在尝试在java中实现一个简单的promise系统.我是为特殊目的而做的,所以请不要推荐任何图书馆.
当我尝试实现一个带有Function作为参数的thenApply()方法时,我遇到了一个问题,类似于CompletableFuture,因此返回另一个类型的promise.
承诺界面:
public interface Promise<T> {
Promise<T> then(Consumer<T> handler);
<U> Promise<U> thenApply(Function<T, U> handler);
}
到目前为止我的实施:
public class PromiseImpl<T> implements Promise<T> {
private List<Consumer<T>> resultHandlers = new ArrayList<>();
public PromiseImpl(CompletableFuture<T> future) {
future.thenAccept(this::doWork);
}
@Override
public Promise<T> then(Consumer<T> handler) {
resultHandlers.add(handler);
return this;
}
@Override
public <U> Promise<U> thenApply(Function<T, U> handler) {
// How to implement here??? I don't have the result yet
handler.apply(?);
}
private void onResult(T result) {
for (Consumer<T> handler : resultHandlers) {
handler.accept(result);
}
}
private Object doWork(T result) {
onResult(result);
return null;
}
}
问题是我在thenApply()方法中不知道我最初的未来结果,所以我无法调用我的处理程序.另外,我不想调用future.get(),因为此方法是阻塞的.
我怎么能做这个工作?
解决方法:
真正的问题在于你的Promise类型的设计.它持有一组回调,所有这些回调都将在完成时调用.这是一个基本问题(限制thenApply函数返回类型的通用功能).这可以通过更改Promise实现来解决,每当注册一个处理程序时返回一个新的promise,而不是返回它,这样每个promise对象都有自己的调用处理程序.
除了解决这个问题之外,它还是功能样式编程的更好设计,因为您可以使Promise对象不可变.
我会将界面更改为:
interface Promise<T> {
<U> Promise<U> thenApply(Function<T, U> handler);
Promise<Void> thenAccept(Consumer<T> consumer);
}
然后可以围绕链接的Promise实例引用的未来对象来完成回调的“链接”.所以实现看起来像:
class PromiseImpl<T> implements Promise<T> {
private CompletableFuture<T> future;
public PromiseImpl(CompletableFuture<T> future) {
this.future = future;
}
@Override
public <U> Promise<U> thenApply(Function<T, U> function) {
return new PromiseImpl<>(this.future.thenApply(function));
}
@Override
public Promise<Void> thenAccept(Consumer<T> consumer) {
return new PromiseImpl<>(this.future.thenAccept(consumer));
}
private void onResult(T result) {
this.future.complete(result);
}
private Object doWork(T result) {
onResult(result);
return null;
}
}
使用它可以很简单:
Promise<String> stringPromise = new PromiseImpl<>(new CompletableFuture<String>());
Promise<Long> longPromise = stringPromise.thenApply(str -> Long.valueOf(str.length()));
Promise<Void> voidPromise = stringPromise.thenAccept(str -> System.out.println(str));
编辑:
关于检索值的Michael’s comment:未添加的值,因为它不在原始的Promise API中.但它很容易添加:
T get(); //To the interface
并实施:
public T get() {
//try-catch
return this.future.get();
}
注意:这开始看起来越来越像CompletableFuture的重复,这引发了为什么要这样做的问题.但假设此接口中将有其他类似Promise的方法,该方法将包装未来的API.
如果需要使用带有回调列表的相同Promise对象,那么除了使用Function具体类型参数参数化Promise接口之外别无选择:
public interface Promise<T, U>
并且U将无法成为then或thenApply上的方法泛型参数.
原文地址:https://codeday.me/bug/20190828/1746882.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。