当谈论期货和回调时, 文件 说
Vert.x核心API是基于回调来通知异步事件的。经验丰富的开发者自然会认为这为所谓的 "回调地狱 "打开了大门,多层嵌套的回调使得代码难以理解,这段虚构的代码就说明了这一点。
foo.a(1, res1 -> {
if (res1.succeeded()) {
bar.b("abc", 1, res2 -> {
if (res.succeeded()) {
baz.c(res3 -> {
dosomething(res1, res2, res3, res4 -> {
// (...)
});
});
}
});
}
});
虽然核心API可以被设计成倾向于承诺和期货,但选择回调作为主要模型其实很有趣,因为它允许使用不同的编程抽象。
意思是Vert.x核心异步API都是以回调作为输入,用这个回调来处理反应API调用的异步结果。如果是基于Futures,而不是这样的API。
void deployVerticle(Verticle verticle, Handler<AsyncResult<String>>
completionHandler);
它应该是这样的
Future<String> deployVerticle(Verticle verticle);
所以,与其说是接受一个回调,得到一个... ... AsyncResult<String>
作为输入,它返回一个 Future<String>
. 然而, 在Vert.x 4.0中,Vert.x团队正在转向基于CallbackFuture的混合模型,所以这两种API将在不久的将来成为Vert.x核心API的一部分。因此,这两种 API 将在不久的将来成为 Vert.x 核心 API 的一部分。
我相信这里的cardinal是用来表示 "基本 "的。所以它只是意味着Vert.x本身在自己的实现中使用回调。然后它使用代码生成和或其他技术来派生其他种类的API抽象。比如返回期货的API,或者返回 RxJava 类型,或者可以作为 Kotlin coroutines等。
一般来说,Futures比回调更容易操作,特别是当你必须将几个异步操作编译在一起的时候。例如,你在原问题中包含的代码可能可以这样写,使用Futures。
CompositeFuture.all(foo.a(1), bar.b("abc", 1), baz.c())
.compose(fut -> doSomething(fut.resultAt(0), fut.resultAt(1),
fut.resultAt(2)))
.compose(res4 -> ...)