与 vertx 组合用于顺序代码
compose with vertx for sequential code
我有两个操作 step_1() 和 step_2() 并且想在 step_1() 之后执行 step_2()。
正常 java 这将是:
step_1();
step_2();
对于 vertx,我必须使用 vertx-compose()。我说得对吗?
根据 https://groups.google.com/forum/#!topic/vertx/FuvlPLpoGOA,顺序代码不需要 Futures。
"If you want to do each request sequencially you dont need futures."
那么我如何在不使用期货的情况下做到这一点?
我不知道,这是否重要:执行此代码的我的 Vertx 是一个 "Worker"-Verticle。
@Override
public void start(Future<Void> fut) throws IOException {
Future<Void> step_1 = Future.future();
step_1.compose(res -> {
// If the future succeeded
Future<Void> step_2 = step_1();
step_2.compose(res2 -> {
step_2();
}, Future.future().setHandler(handler -> {
// If the future failed
}));
//I dont need that
}, Future.future().setHandler(handler -> {
// If the future failed
}));
}
public void step_1(){
..
}
public void step_2(){
..
}
这是正确且最短 (!) 的方式吗?
将 step_2
作为参数传递给 step_1
@Override
public void start(Future<Void> fut) throws IOException {
step_1(step_2);
}
private void step_1(Runnable function){
someAsynccall("some-arg", response -> {
function.run();
}).end();
}
private void step_2(){
// do something
}
"If you want to do each request sequencially you dont need futures."
不,不是。在 Vert.x、input/output 等异步框架中,操作是非阻塞的。这意味着,如果您调用几个异步操作,它们将同时开始工作。如果你想连续执行几个请求,那么你应该使用期货或回调只有在前一个请求成功完成后才执行新请求。
检查这个关于项目的code with futures, newer version with RxJava 2 and article。
@Override
public Future<Optional<Todo>> getCertain(String todoID) {
Future<Optional<Todo>> result = Future.future();
redis.hget(Constants.REDIS_TODO_KEY, todoID, res -> {
if (res.succeeded()) {
result.complete(Optional.ofNullable(
res.result() == null ? null : new Todo(res.result())));
} else
result.fail(res.cause());
});
return result;
}
@Override
public Future<Todo> update(String todoId, Todo newTodo) {
return this.getCertain(todoId).compose(old -> {
if (old.isPresent()) {
Todo fnTodo = old.get().merge(newTodo);
return this.insert(fnTodo)
.map(r -> r ? fnTodo : null);
} else {
return Future.succeededFuture();
}
});
}
RxJava 专门用于编写异步事件:http://vertx.io/docs/vertx-rx/java/
假设 step_1() 和 step_1() 都不是为了 return 结果而设计的(即它们实际上 return void) 那么你可以将它们更改为 return Observable 或 Single 并将它们链接在一起,类似于:
step_1().doOnSuccess(this::step_2()).subscribe(/* control resumes here */);
RxJava(或者更确切地说,一般的反应式编程)需要一点时间来理解它,但如果您打算将异步操作链接在一起,我强烈建议您使用它。
下面是 Future
的链接示例,我已经使这个示例非常简单,但它展示了这个概念。
@RunWith(VertxUnitRunner.class)
public class Chaining {
private Vertx vertx = Vertx.vertx();
@Test
public void futures_chaining(TestContext context) throws Exception {
Async async = context.async();
firstOperation()
.compose((outcome) -> {
System.out.println(outcome);
return secondOperation();
})
.compose(outcome -> {
System.out.println(outcome);
/*
For stopping unit test we are returning this future
for production use-case this would be Future.succeededFuture
or Future.failedFuture depending on your method outcomes
*/
return Future.future(handle -> async.complete());
});
}
private Future<String> firstOperation() {
Future<String> future = Future.future();
vertx.setTimer(1000, delay -> future.complete("First Operation Complete"));
return future;
}
private Future<String> secondOperation() {
Future<String> future = Future.future();
vertx.setTimer(1000, delay -> future.complete("Second Operation Complete"));
return future;
}
}
我有两个操作 step_1() 和 step_2() 并且想在 step_1() 之后执行 step_2()。
正常 java 这将是:
step_1();
step_2();
对于 vertx,我必须使用 vertx-compose()。我说得对吗?
根据 https://groups.google.com/forum/#!topic/vertx/FuvlPLpoGOA,顺序代码不需要 Futures。
"If you want to do each request sequencially you dont need futures."
那么我如何在不使用期货的情况下做到这一点?
我不知道,这是否重要:执行此代码的我的 Vertx 是一个 "Worker"-Verticle。
@Override
public void start(Future<Void> fut) throws IOException {
Future<Void> step_1 = Future.future();
step_1.compose(res -> {
// If the future succeeded
Future<Void> step_2 = step_1();
step_2.compose(res2 -> {
step_2();
}, Future.future().setHandler(handler -> {
// If the future failed
}));
//I dont need that
}, Future.future().setHandler(handler -> {
// If the future failed
}));
}
public void step_1(){
..
}
public void step_2(){
..
}
这是正确且最短 (!) 的方式吗?
将 step_2
作为参数传递给 step_1
@Override
public void start(Future<Void> fut) throws IOException {
step_1(step_2);
}
private void step_1(Runnable function){
someAsynccall("some-arg", response -> {
function.run();
}).end();
}
private void step_2(){
// do something
}
"If you want to do each request sequencially you dont need futures."
不,不是。在 Vert.x、input/output 等异步框架中,操作是非阻塞的。这意味着,如果您调用几个异步操作,它们将同时开始工作。如果你想连续执行几个请求,那么你应该使用期货或回调只有在前一个请求成功完成后才执行新请求。
检查这个关于项目的code with futures, newer version with RxJava 2 and article。
@Override
public Future<Optional<Todo>> getCertain(String todoID) {
Future<Optional<Todo>> result = Future.future();
redis.hget(Constants.REDIS_TODO_KEY, todoID, res -> {
if (res.succeeded()) {
result.complete(Optional.ofNullable(
res.result() == null ? null : new Todo(res.result())));
} else
result.fail(res.cause());
});
return result;
}
@Override
public Future<Todo> update(String todoId, Todo newTodo) {
return this.getCertain(todoId).compose(old -> {
if (old.isPresent()) {
Todo fnTodo = old.get().merge(newTodo);
return this.insert(fnTodo)
.map(r -> r ? fnTodo : null);
} else {
return Future.succeededFuture();
}
});
}
RxJava 专门用于编写异步事件:http://vertx.io/docs/vertx-rx/java/
假设 step_1() 和 step_1() 都不是为了 return 结果而设计的(即它们实际上 return void) 那么你可以将它们更改为 return Observable 或 Single 并将它们链接在一起,类似于:
step_1().doOnSuccess(this::step_2()).subscribe(/* control resumes here */);
RxJava(或者更确切地说,一般的反应式编程)需要一点时间来理解它,但如果您打算将异步操作链接在一起,我强烈建议您使用它。
下面是 Future
的链接示例,我已经使这个示例非常简单,但它展示了这个概念。
@RunWith(VertxUnitRunner.class)
public class Chaining {
private Vertx vertx = Vertx.vertx();
@Test
public void futures_chaining(TestContext context) throws Exception {
Async async = context.async();
firstOperation()
.compose((outcome) -> {
System.out.println(outcome);
return secondOperation();
})
.compose(outcome -> {
System.out.println(outcome);
/*
For stopping unit test we are returning this future
for production use-case this would be Future.succeededFuture
or Future.failedFuture depending on your method outcomes
*/
return Future.future(handle -> async.complete());
});
}
private Future<String> firstOperation() {
Future<String> future = Future.future();
vertx.setTimer(1000, delay -> future.complete("First Operation Complete"));
return future;
}
private Future<String> secondOperation() {
Future<String> future = Future.future();
vertx.setTimer(1000, delay -> future.complete("Second Operation Complete"));
return future;
}
}