您可以使用CompletableFuture 在 Java 中实现 Promise。问题是,您试图通过“管道”传递两种不同的东西:请求是可变的并且(有时)会发生变化,而结果是在调用过程中累积的。
我通过创建一个名为Pipe 的类来解决这个问题,该类有一个请求,以及迄今为止结果的累加器。它对两者都有 getter,并且它有一些方便的方法来返回一个带有累积结果的新对象,甚至可以改变请求并在一次调用中累积。这使得 API 链接的代码更加简洁。
字段、构造函数和getter 之后的with* 方法是处理累积和变异的方法。 chain 方法将它们放在一起:
import java.util.concurrent.CompletableFuture;
public class Pipe {
private Request req;
private String out;
public Pipe(Request req, String out) {
this.req = req;
this.out = out;
}
public Request getReq() {
return req;
}
public String getOut() {
return out;
}
public Pipe with(String data) {
return new Pipe(req, out + data);
}
public Pipe withABC(String abc, String data) {
req.setABC(abc);
return new Pipe(req, out + data);
}
public Pipe withXYZ(String xyz, String data) {
req.setXYZ(xyz);
return new Pipe(req, out + data);
}
public static void chain(Request req) throws Exception {
var promise = CompletableFuture.supplyAsync(() -> new Pipe(req, ""))
.thenApply(pipe -> {
Response res = execute(pipe.getReq());
return pipe.withABC(res.getABC(), res.getOut());
})
.thenApply(pipe -> {
Response res = execute(pipe.getReq());
return pipe.withXYZ(res.getXYZ(), res.getOut());
})
.thenApply(pipe -> {
Response res = execute(pipe.getReq());
return pipe.with(res.getOut());
});
var result = promise.get().getOut();
System.out.println(result);
}
public static Response execute(Request req) {
return req.getResponse();
}
}
因为它是异步运行的,所以它可以抛出InterruptedException,如果其他东西中断它也可以抛出ExecutionException。我不知道你想怎么处理,所以我只是宣布chain 扔。
如果你想在循环中应用 n 操作,你必须不断地重新分配承诺,如下所示:
var promise = CompletableFuture.supplyAsync(() -> new Pipe(req, ""));
for (...) {
promise = promise.thenApply(pipe -> {
Response res = execute(pipe.getReq());
return pipe.with(res.getOut());
});
}
var result = promise.get().getOut();
我在这里使用了带有var 的Java 10 类型推断,但promise 和result 的类型将分别为CompletableFuture<Pipe> 和String。
(注意:最好使Request 不可变,并在管道中传递一个新的、已更改的,而不是对其进行变异。另一方面,您也可以包装StringBuilder 而不是String ,并且让你积累的数据也是可变的。现在它是可变和不可变的奇怪组合,但这与你的代码正在做的事情相匹配。)