java8 CompletableFuture 与 es6 Promise 对比分析

1. 时间线和借鉴关系

时间线

  • JavaScript Promise:最早出现在 2007 年(Dojo 框架),2015 年成为 ES6 标准

  • Java CompletableFuture:2014 年随 Java 8 引入

借鉴关系

  • CompletableFuture 借鉴了 Promise 的核心思想,但扩展了更多功能:

  • 两者都实现了 Future 模式

  • 都支持链式调用和组合操作

  • CompletableFuture 从 JavaScript Promise(以及 Scala、C# 等语言)中汲取了设计灵感

  • 但 CompletableFuture 提供了更丰富的 API,更像是一个"Promise on steroids"

2. 核心 API 对比

功能分类 CompletableFuture (Java) Promise (ES6+) 备注
创建 supplyAsync(), runAsync(), completedFuture() new Promise(), Promise.resolve(), Promise.reject()
转换 thenApply(), thenAccept(), thenRun() then() CompletableFuture 更细粒度
组合 thenCompose(), thenCombine(), acceptEither() then() 链式调用 CompletableFuture 更丰富
多任务组合 allOf(), anyOf() all(), race(), allSettled(), any() ES2021 新增 any()
异常处理 exceptionally(), handle(), whenComplete() catch(), finally() CompletableFuture 更灵活
完成控制 complete(), completeExceptionally(), obtrudeValue() 只能在 executor 中 resolve/reject CompletableFuture 可外部完成
超时控制 orTimeout(), completeOnTimeout() (Java 9+) 需要自己实现或使用 Promise.race CompletableFuture 内置支持
结果依赖 thenApplyAsync(), thenComposeAsync() 等带 Async 的方法 then() 自动异步 CompletableFuture 可指定线程池
获取结果 get(), join(), getNow() await (async/await)
取消操作 cancel() 无内置取消机制
延迟执行 需要手动实现 new Promise() 立即执行
进度报告 无内置支持 无内置支持 都需要自己实现
  • 创建异步任务
// CompletableFuture
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "result");
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {});

// 手动控制完成
CompletableFuture<String> future3 = new CompletableFuture<>();
future3.complete("result");
future3.completeExceptionally(new Exception());
// Promise
const promise = new Promise((resolve, reject) => {
    // 异步操作
    resolve("result");
    // 或 reject(new Error())
});
  • 转换和组合
// CompletableFuture
future.thenApply(result -> result + " transformed")
      .thenAccept(System.out::println)
      .thenRun(() -> System.out.println("Done"));

// 组合多个Future
CompletableFuture.allOf(future1, future2);
CompletableFuture.anyOf(future1, future2);
// Promise
promise.then(result => result + " transformed")
       .then(console.log)
       .then(() => console.log("Done"));

// 组合多个Promise
Promise.all([promise1, promise2]);
Promise.race([promise1, promise2]); // 类似 anyOf
Promise.allSettled([promise1, promise2]);
  • 异常处理
// CompletableFuture
future.exceptionally(ex -> "fallback")
       .handle((result, ex) -> {
           // 同时处理结果和异常
           return ex != null ? "error" : result;
       })
       .whenComplete((result, ex) -> {
           // 清理操作,类似 finally
       });
// Promise
promise.catch(error => "fallback")
       .finally(() => {
           // 清理操作
       });

// 没有直接的 handle 方法,需要自己包装

3. 特色功能对比

CompletableFuture 特有功能

// 1. 手动完成(从外部完成Future)
CompletableFuture<String> future = new CompletableFuture<>();
new Thread(() -> {
    // 某个条件达成后
    future.complete("done");
}).start();

// 2. 依赖多个Future的结果
future1.thenCombine(future2, (r1, r2) -> r1 + r2);
future1.thenAcceptBoth(future2, (r1, r2) -> System.out.println(r1 + r2));

// 3. 竞争第一个完成的(但处理所有结果)
future1.applyToEither(future2, result -> result);

// 4. 超时控制(Java 9+)
future.orTimeout(1, TimeUnit.SECONDS);
future.completeOnTimeout("default", 1, TimeUnit.SECONDS);

// 5. 指定执行线程池
future.thenApplyAsync(transformation, customExecutor);

Promise 特有功能

// 1. async/await 语法糖(ES2017+)
async function fetchData() {
    try {
        const result = await promise;
        console.log(result);
    } catch (error) {
        console.error(error);
    }
}

// 2. Promise.allSettled() (ES2020)
// 等待所有Promise完成,无论成功失败
Promise.allSettled([promise1, promise2])
    .then(results => {
        results.forEach(result => {
            if (result.status === 'fulfilled') {
                console.log('成功:', result.value);
            } else {
                console.log('失败:', result.reason);
            }
        });
    });

// 3. 微任务队列
// Promise回调在微任务队列执行,优先级高于宏任务

4. 设计哲学差异

CompletableFuture 特点:

  • 功能丰富:提供了大量的组合方法

  • 显式控制:可以手动完成、取消、指定执行器

  • 同步点:提供了 get()、join() 等阻塞方法

  • 集成并发工具:与 Java 的 Executor 框架深度集成

Promise 特点:

  • 简单一致:API 相对简单,核心是 then/catch/finally

  • 不可取消:一旦创建,无法从外部取消

  • 微任务调度:基于事件循环,回调在微任务队列执行

  • 语言级集成:与 async/await 语法深度集成

5. 使用场景建议

使用 CompletableFuture 当:

// 需要复杂组合逻辑
CompletableFuture<List<String>> result = 
    CompletableFuture.supplyAsync(() -> fetchUsers())
        .thenCompose(users -> 
            CompletableFuture.supplyAsync(() -> processUsers(users))
        )
        .exceptionally(ex -> fallbackList());

// 需要手动控制完成
CompletableFuture<Data> cacheFuture = new CompletableFuture<>();
if (cache.hasData()) {
    cacheFuture.complete(cache.getData());
} else {
    loadDataAsync().thenAccept(data -> {
        cache.setData(data);
        cacheFuture.complete(data);
    });
}

// 需要超时控制
future.orTimeout(5, TimeUnit.SECONDS)
      .exceptionally(ex -> defaultData());

使用 Promise 当:

// 简单异步流程
fetch(url)
    .then(response => response.json())
    .then(data => process(data))
    .catch(error => handleError(error))
    .finally(() => cleanup());

// 使用 async/await 简化
async function processUser(userId) {
    try {
        const user = await fetchUser(userId);
        const orders = await fetchOrders(user.id);
        return { user, orders };
    } catch (error) {
        console.error(error);
        return null;
    }
}

// 并行处理多个异步任务
const [user, products] = await Promise.all([
    fetchUser(),
    fetchProducts()
]);

6. 总结

相同点:

  • 都实现了 Future/Promise 模式

  • 都支持链式调用和组合

  • 都用于解决回调地狱问题

主要差异:

维度 CompletableFuture Promise
设计理念 功能全面,适合复杂业务逻辑 简单一致,适合Web异步编程
完成控制 可以从外部手动完成 只能在executor内部完成
取消机制 支持取消 不支持
线程控制 可以指定执行器 由事件循环控制
语法集成 没有特殊语法糖 有 async/await 语法糖
多任务组合 方法更丰富(thenCombine等) 提供静态方法(all/race等)

发展趋势:

  • Promise 影响了 CompletableFuture 的设计

  • CompletableFuture 反过来又影响了后续的 JavaScript 提案(如取消机制的讨论)

  • 两者都在各自生态中持续演进,吸收对方优点

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐