在CompletableFuture中链接以返回第一个值

时间:2017-09-20 05:48:00

标签: java completable-future

我有一些代码使用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
}

现在,我不想从void方法返回save。我想要返回MyEntity,所以我尝试了:

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

这不起作用,因为runAsync返回void。我的方法repository.save()返回我想要返回的对象,但该调用位于链的开头。我需要先保存对象,然后才能执行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现在必须在同一阶段执行,可能需要一些时间。

如何在repository.save()foo正确完成后返回bar中保存的对象?

2 个答案:

答案 0 :(得分:1)

如果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。我最终也避免了捕获。

如果我们在thenCombinefooFuture上退回实体,我们可以避免一个barFuture

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);
}

答案 1 :(得分:-1)

你可以用一个做东西的方法来链接并返回输入:

 <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title> Hello app </title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
    </head>
    <body>
    <div ng-app="testapp" ng-controller="test">
        <p> Enter your name: <input type="text" ng-model="name"></p>
        <p> Enter your age here: <input type="text" ng-model="age"> </p>
        <ol>
          <li> My Name is {{ name }} </li>
          <li>I am {{ age}} years old </li>
        </ol>
 
   </div>
   </body>
   </html>