将 CompletableFuture 链接到 return 第一个值

Chaining in CompletableFuture to return first value

我有一些代码使用 spring-data 将实体保存到数据库,然后执行一些其他工作 foo()bar() 需要来自实体的 id已保存。看起来像这样:

private CompletableFuture<Void> save(MyEntity me) {
    CompletableFuture<Void> future = ContextAwareCompletableFuture
        .runAsync(() -> repository.save(me))
        .thenRunAsync(() -> foo(me))
        .thenRunAsync(() -> bar(me));
    return future;
}

private Foo foo(MyEntitiy me) {
    // Use the identifier for me to update some foo in another world
}

private Bar bar(MyEntitiy me) {
    // Use the identifier for me to update some bar in at another time
}

现在,我不想从我的 save 方法中 return void。我想 return 一个 MyEntity 所以我尝试了:

private CompletableFuture<MyEntity> save(MyEntity me) {
    CompletableFuture<MyEntity> future = ContextAwareCompletableFuture
        .runAsync(() -> repository.save(me))
        .thenRunAsync(() -> foo(me))
        .thenRunAsync(() -> bar(me));
    return future;
}

这不起作用,因为 runAsync return 无效。我的方法 repository.save() return 是我希望 return 的对象,但该调用位于链的开头。我需要先保存对象,然后才能执行 foobar.

所以接下来我尝试的是:

private CompletableFuture<MyEntity> save(MyEntity me) {
    CompletableFuture<MyEntity> future = ContextAwareCompletableFuture
        .supplyAsync(() -> repository.save(me))
        .thenApplyAsync((e) -> baz(e);
    return future;
}

private MyEntity baz(MyEntitiy me) {
    foo(me);
    bar(me);
    return me;
}

现在,这对我来说似乎是错误的。 FooBar 现在必须在同一阶段执行,它们可能需要一些时间。

如何在 foobar 正确完成后 return 保存在 repository.save() 中的对象?

你可以链接一个做东西的方法和returns输入:

.thenApply(e -> { foo(e); return e; }

如果 foobar 可以同时 运行,您可以选择链接 save 而不是对它们进行排序:

private CompletableFuture<MyEntity> save(MyEntity me) {
    CompletableFuture<MyEntity> future = ContextAwareCompletableFuture
        .supplyAsync(() -> repository.save(me));
    CompletableFuture<Void> fooFuture = future
        .thenAcceptAsync((e) -> foo(e));
    CompletableFuture<Void> barFuture = future
        .thenAcceptAsync((e) -> bar(e));
    return future
        .thenCombine(fooFuture, (result, fooResult) -> result)
        .thenCombine(barFuture, (result, barResult) -> result);
}

注意我使用 thenAcceptAsync 而不是 thenRunAsync 以避免捕获 me。最后我也躲过了被抓

如果我们 return fooFuturebarFuture 上的实体,我们可以避免一个 thenCombine:

private CompletableFuture<MyEntity> save(MyEntity me) {
    CompletableFuture<MyEntity> future = ContextAwareCompletableFuture
        .supplyAsync(() -> repository.save(me));
    CompletableFuture<MyEntity> fooFuture = future
        .thenApplyAsync((e) -> { foo(e); return e; });
    CompletableFuture<MyEntity> barFuture = future
        .thenApplyAsync((e) -> { bar(e); return e; });
    return fooFuture
        .thenCombine(barFuture, (fooResult, barResult) -> fooResult);
}