Vert.x:如何等待将来完成

时间:2018-11-18 09:45:54

标签: vert.x

有没有办法等待将来完成而不会阻塞事件循环?

查询Mongo的用例示例:

Future<Result> dbFut = Future.future();
mongo.findOne("myusers", myQuery, new JsonObject(), res -> {
    if(res.succeeded()) {
      ...
      dbFut.complete(res.result());
    }
    else {
      ...
      dbFut.fail(res.cause());
    }
  }
  });

// Here I need the result of the DB query
if(dbFut.succeeded()) {
  doSomethingWith(dbFut.result());
}
else {
  error();
}

我知道doSomethingWith(dbFut.result());可以移到处理程序,但是如果很长,代码将变得不可读(回调地狱?),那是正确的解决方案吗?那是没有其他库的全能解决方案吗?

我知道rxJava简化了代码,但据我所知,学习Vert.x 实在太多了。

我还想尝试vertx-sync。我将依赖项放在pom.xml中;一切下载正常,但是当我启动应用程序时,出现以下错误

maurice@mickey> java \
  -javaagent:~/.m2/repository/co/paralleluniverse/quasar-core/0.7.5/quasar-core-0.7.5-jdk8.jar \
  -jar target/app-dev-0.1-fat.jar \
  -conf conf/config.json 
Error opening zip file or JAR manifest missing : ~/.m2/repository/co/paralleluniverse/quasar-core/0.7.5/quasar-core-0.7.5-jdk8.jar
Error occurred during initialization of VM
agent library failed to init: instrument

我知道该错误通常意味着什么,但是在这种情况下我不知道...我尝试用Google搜索它,但是没有找到关于放置在哪个清单的明确解释。和以前一样,除非是强制性的,否则我宁愿一次学习一件事。

因此,回到问题所在:是否有一种“基本” Vert.x可以在将来不受事件循环干扰的情况下等待未来?

2 个答案:

答案 0 :(得分:3)

您可以设置一个处理程序,以便将来在完成或失败时执行:

Future<Result> dbFut = Future.future();
mongo.findOne("myusers", myQuery, new JsonObject(), res -> {
    if(res.succeeded()) {
      ...
      dbFut.complete(res.result());
    }
    else {
      ...
      dbFut.fail(res.cause());
    }
  }
  });

dbFut.setHandler(asyncResult -> {
    if(asyncResult.succeeded()) {
      // your logic here
    }
});

这是不会阻止事件循环的纯Vert.x方式

答案 1 :(得分:0)

我同意您不应阻塞 Vertx 处理管道,但我对该规则提出了一个例外:启动。根据设计,我想在我的 HTTP 服务器初始化时阻塞。

此代码可能对您有所帮助:

/**
 * @return null when waiting on {@code Future<Void>}
 */
@Nullable
public static <T>
T awaitComplete(Future<T> f)
throws Throwable
{
    final Object lock = new Object();
    final AtomicReference<AsyncResult<T>> resultRef = new AtomicReference<>(null);
    synchronized (lock)
    {
        // We *must* be locked before registering a callback.
        // If result is ready, the callback is called immediately!
        f.onComplete(
            (AsyncResult<T> result) ->
            {
                resultRef.set(result);
                synchronized (lock) {
                    lock.notify();
                }
            });

        do {
            // Nested sync on lock is fine.  If we get a spurious wake-up before resultRef is set, we need to
            // reacquire the lock, then wait again.
            // Ref: https://stackoverflow.com/a/249907/257299
            synchronized (lock)
            {
                // @Blocking
                lock.wait();
            }
        }
        while (null == resultRef.get());
    }
    final AsyncResult<T> result = resultRef.get();
    @Nullable
    final Throwable t = result.cause();
    if (null != t) {
        throw t;
    }
    @Nullable
    final T x = result.result();
    return x;
}