简体   繁体   English

使用CompletableFuture进行回调

[英]Callback with CompletableFuture

I'm trying to create a really simple callback using some Strings. 我正在尝试使用一些字符串创建一个非常简单的回调。 The IDE's code sense is is moaning about an unchecked call to exceptionally. IDE的代码含义是抱怨异常的未经检查的调用。 Can anyone give me a fix for this? 谁能解决这个问题? The idea in the end is to wrap a network call so that the promised result is returned and I can tack on additional functions as needed. 最后的想法是包装一个网络调用,以便返回预期的结果,我可以根据需要添加其他功能。

import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class FuturesTest {

    public static void main(String[] args) throws Exception {
        new FuturesTest().go();
    }

    private void go() throws ExecutionException, InterruptedException {
        CompletableFuture.supplyAsync(new MakesANetworkCall())
                .whenComplete(new BiConsumer<String, String>() {
                    @Override
                    public void accept(String result, String s) {
                        System.out.println(result.toString());
                    }
                })
                .exceptionally(new Function<Exception, Exception>() {
                                   @Override
                                   public Exception apply(Exception e) {
                                       e.printStackTrace();
                                       return e;
                                   }
                               }
                ).thenApplyAsync(new Function<String, String>() {
                    @Override
                    public String apply(String o) {
                        System.out.println("Last action of all!");
                        return null;
                    }
                });

        System.out.println("Main thread will sleep");
        Thread.sleep(2500);
        System.out.println("Program over");
    }

    class MakesANetworkCall implements Supplier {

        @Override
        public String get() {
            try {
                System.out.println("Ground control to Major Tom");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            int i = 2/0;
            return new String("Major Tom reporting!");
        }
    }
}

First of all, your class MakesANetworkCall implements the raw type Supplier instead of Supplier<String> . 首先,您的类MakesANetworkCall实现原始类型Supplier而不是Supplier<String> This will effectively disable the type checking and hide all errors you made, so it's not the single warning you should worry about, as that's not the only thing wrong in your code: 这将有效地禁用类型检查并隐藏您所犯的所有错误,因此这不是您应该担心的单个警告,因为这不是代码中唯一的错误:

  • The BiConsumer passed to whenComplete should be able to consume a Throwable as its second argument. BiConsumer传递给whenComplete应该能够消耗Throwable作为第二个参数。

  • The Function passed to exceptionally should consume a Throwable and return an alternative result. 传递给exceptionallyFunction应该消耗Throwable并返回替代结果。

Further, you are invoking a static method using the expression new CompletableFuture<String>() as its target and you have an obsolete string creation expression as new String("Major Tom reporting!") where the simple constant "Major Tom reporting!" 此外,您正在使用表达式new CompletableFuture<String>()作为目标来调用static方法,并且具有过时的字​​符串创建表达式作为new String("Major Tom reporting!") ,其中简单常量"Major Tom reporting!" will do. 会做。 Generally, you seem to try to always use an inappropriate method, ie one designed to consume things you don't use or one for supplying a value where you don't have one. 通常,您似乎总是尝试使用一种不合适的方法,例如,一种旨在消耗您不使用的东西的方法,或者一种用于提供您没有的东西的价值的方法。 Consider this: 考虑一下:

CompletableFuture.supplyAsync(new MakesANetworkCall())
    .thenAccept(result -> System.out.println(result))
    .exceptionally(e -> { e.printStackTrace(); return null;})
    .thenRun(()->System.out.println("Last action of all!"));

This does what seems to be your intention. 这似乎是您的意图。 If you ensure that your MakesANetworkCall correctly implements Supplier<String> , this should compile without any warnings. 如果确保MakesANetworkCall正确实现了Supplier<String> ,则应在编译时没有任何警告。

Your core issue is with class MakesANetworkCall implements Supplier { . 您的核心问题是class MakesANetworkCall implements Supplier { This is using raw types and therefore hides further problems. 这使用的是原始类型,因此隐藏了更多问题。 Fix that to class MakesANetworkCall implements Supplier<String> { and fix all ensuing issues and you get: 修复该问题,使class MakesANetworkCall implements Supplier<String> {并解决所有随之而来的问题,您将获得:

    CompletableFuture.supplyAsync(new MakesANetworkCall())
            // Not <String, String>
            .whenComplete(new BiConsumer<String, Throwable>() {
                @Override
                public void accept(String result, Throwable t) {
                    System.out.println(result);
                }
            })
            // Not <Exception,Exception>
            .exceptionally(new Function<Throwable, String>() {
                @Override
                public String apply(Throwable t) {
                    t.printStackTrace();
                    // Must return a Streing
                    return t.getMessage();
                }
            }
            ).thenApplyAsync(new Function<String, String>() {
                @Override
                public String apply(String o) {
                    System.out.println("Last action of all!");
                    return null;
                }
            });

CompletableFuture.exceptionally is declared like so: 像这样声明CompletableFuture.exceptionally

public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn);

You're passing it a Function<Exception, Exception> , whereas you should be passing it a Function<Throwable, String> . 您正在传递给它一个Function<Exception, Exception> ,而应该传递给它一个Function<Throwable, String>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM