【问题标题】:compose with vertx for sequential code用 vertx 编写顺序代码
【发布时间】:2017-06-12 09:19:12
【问题描述】:

我有两个操作 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 用于顺序代码。

“如果您想按顺序执行每个请求,则不需要期货。”

那么我怎么能不使用期货呢?

我不知道这是否重要:执行此代码的我的 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_1() 定义为返回void,但您显示的好像是从中获得Future,您的意图是清楚你想要step1 执行然后执行step2,它们本质上是blocking,这就是你想要workerverticle 的原因。请澄清,以便我们可以更好地为您服务。
  • 我得到了一个未来。但是,我唯一需要的是制作“step1”然后制作“step2”。我猜,“worker verticle”不会使整个代码在 start-method 中阻塞,或者?如果是这样,那么我不需要 Future.
  • 谢谢,确实你是对的 Worker verticle 没有那种魔法

标签: vert.x


【解决方案1】:

下面是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;
    }
}

【讨论】:

    【解决方案2】:

    “如果您想按顺序执行每个请求,则不需要期货。”

    不,不是。在像 Vert.x 这样的异步框架中,输入/输出操作是非阻塞的。这意味着,如果您调用一些异步操作,它们将同时开始工作。如果你想顺序执行几个请求,那么你应该使用futures或callbacks在前一个成功完成后才执行新的请求。

    检查code 与期货,newer version 与 RxJava 2 和 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();
            }
        });
    }
    

    【讨论】:

      【解决方案3】:

      RxJava 专门用于编写异步事件:http://vertx.io/docs/vertx-rx/java/

      假设 step_1() 和 step_1() 都不是为返回结果而设计的(即它们实际上返回 void),那么您可以将它们更改为返回 Observable 或 Single 并将它们链接在一起,类似于此:

      step_1().doOnSuccess(this::step_2()).subscribe(/* control resumes here */);
      

      RxJava(或者更确切地说,一般的反应式编程)需要一点时间来理解它,但如果您打算将异步操作链接在一起,我强烈建议您使用它。

      【讨论】:

        【解决方案4】:

        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
        }
        

        【讨论】:

          猜你喜欢
          • 2020-12-25
          • 1970-01-01
          • 2021-02-25
          • 1970-01-01
          • 2021-09-04
          • 1970-01-01
          • 2014-02-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多