如何在java中实现更改输出类型的promise

我正在尝试在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上的方法泛型参数.

相关文章

最后的控制台返回空数组.控制台在ids.map函数完成之前运行va...
我正在尝试将rxJava与我已经知道的内容联系起来,特别是来自J...
config.jsconstconfig={base_url_api:"https://douban....
我正在阅读MDN中的javascript,并且遇到了这个谈论承诺并且不...
config.jsconstconfig={base_url_api:"https://douban....
这是我的代码main.cpp:#include<string>#include<...