【问题标题】:Javascript Wrapping Callback as Promise Equivalent in Java 8 using CompletableFuture使用 CompletableFuture 在 Java 8 中将 Javascript 包装回调作为 Promise 等价物
【发布时间】:2020-09-11 14:32:20
【问题描述】:

在 Javascript 中,我可以将回调包装为如下的承诺:

function subscribeAsCallback(request, callback) {
    // ... async operation
    const response = ...; 
    callback(response); 
}

function subscribeAsPromise(request) {
    return new Promise((resolve, reject) => {
        subscribeAsCallback(request, (response) => {
            resolve(response);
        });
    });
}

这样我就可以调用它了

subscribeAsPromise(request).then(response => {
   // handling response logic
});

我想问一下它在 Java 中的等价物是什么?这是我在 Java 中的代码,我不知道如何包装回调。

public class DataSubscriber {
    public void subscribeAsCallback(Request request, Consumer<Response> consumer) {
        // ... async operation 
        Response response = ...; 
        consumer.accept(response); 
    }

    public CompletableFuture<Response> subscribeAsPromise(Request request) {
        // ... ? 
        // what is the equivalent of its Java version?
    }
}

这样我就可以这样调用代码了:

dataSubscriber.subscribeAsPromise(request).thenApply(response -> {
   // handling response logic
});

【问题讨论】:

  • 也许我通过搜索找到的20 examples of using CompletableFuture之一就是你想要的
  • 你看过runAsync()吗?
  • 如何使用 runAsync() 返回CompletableFuture&lt;Response&gt;
  • @CHANist 将subscribeAscallback() 方法传递给runAsync() 的lambda 函数。示例here
  • @codemax 抱歉,还是想不通,你能给我一个更具体的例子吗?

标签: javascript java promise callback completable-future


【解决方案1】:

我只是想到了一个使用CountDownLatch 的解决方案,虽然我不认为使用 CountDownLatch 是一个好主意,因为它只会阻止线程执行而浪费一些资源。但这将是一种可能的解决方案。

public class DataSubscriber {
    public void subscribeAsCallback(Request request, Consumer<Response> consumer) {
        // ... async operation 
        Response response = ...; 
        consumer.accept(response); 
    }

    public CompletableFuture<Response> subscribeAsPromise(Request request) {        
        return CompletableFuture.supplyAsync(() -> {
            try {
                final Response[] responeResult = { null }; 
                CountDownLatch latch = new CountDownLatch(1);
                subscribeAsCallback(request, new Consumer<Response>() {
                    public void accept(Response response) {
                        responeResult[0] = response;
                        latch.countDown(); 
                    }
                });

                latch.await();
                return responseResult[0]; 
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        });
    }
}

虽然代码看起来不是很好,但这是我能想到的第一个解决方案。希望有其他更好的答案,以便我学习。

【讨论】:

    【解决方案2】:

    您将无法将callback 传递给CompletableFuture。我个人觉得在JavaScript 中处理promises 更容易,在java 中肯定更冗长。

    在您的示例中,我看不到将匿名函数(response) =&gt; { resolve(response); } 传递给promisefuture 的意义,因为CompletableFuture 提供了一个get() 方法来解析@987654332 @,在你的代码行之后调用

    CompletableFuture future = dataSubscriber.subscribeAsPromise(request).thenApply(response -> {
       // handling response logic
    });
    
    // do this to "resolve" the future
    future.get();
    
    
    public class DataSubscriber {
        // Please update the name to reflect the correct semantic meaning
        public Response subscribeAsCallback(Request request) {
            // ... async operation 
            Response response = ...; 
            return response;
        }
    
        public CompletableFuture<Response> subscribeAsPromise(Request request) {
            return CompletableFuture.supplyAsync(this::subscribeAsCallback);
        }
    }
    
    
    

    【讨论】:

    • 例如,如果我通过socket请求数据,我可以很容易地使用回调来检索数据。肯定 Promise 只会返回一次,而 Socket 可以返回多次,但是如果我确保这样的合约确实存在,那么我可以很容易地使用 Javascript 中的 Promise 通过 socket 包装回调(参见上面的代码)。但是我怎么能在 Java 中做到这一点呢?
    • 我认为我们需要更多的上下文和代码。例如,如果您使用套接字,为什么还需要创建CompletableFuture?数据不应该在事件处理程序中处理吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-24
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多