Mongodb异步java驱动程序find()

ern*_*lez 1 java asynchronous mongodb

我有一个webapp,我必须将结果从mongodb find()返回到我的java后端的前端.我正在使用Async Java驱动程序,我认为我必须从mongo返回结果的唯一方法是这样的:

public String getDocuments(){
  ...
  collection.find(query).map(Document::toJson)
        .into(new HashSet<String>(), new SingleResultCallback<HashSet<String>>() {
            @Override
            public void onResult(HashSet<String> strings, Throwable throwable) {
              // here I have to get all the Json Documents in the set,
              // make a whole json string and wake the main thread
            }
        });
  // here I have to put the main thread to wait until I get the data in
  // the onResult() method so I can return the string back to the front-end
  ...
  return jsonString;
}
Run Code Online (Sandbox Code Playgroud)

这种假设是正确的还是有另一种方式来做到这一点?

Phi*_*ipp 6

异步API(任何基于回调的API,不一定是MongoDB)都可以成为多线程应用程序的真正祝福.但要真正从中受益,您需要以异步方式设计整个应用程序架构.这并不总是可行的,特别是当它应该适合不是基于回调构建的给定框架时.

所以有时候(就像你的情况一样)你只想以同步的方式使用异步API.在这种情况下,您可以使用该类CompletableFuture.

这个类提供了(以及其他)两种方法<T> get()complete(<T> value).该方法get将阻塞,直到complete被调用以提供返回值(应该complete在之前调用get,get立即返回所提供的值).

public String getDocuments(){
  ...
  CompletableFuture<String> result = new CompletableFuture<>(); // <-- create an empty, uncompleted Future

  collection.find(query).map(Document::toJson)
        .into(new HashSet<String>(), new SingleResultCallback<HashSet<String>>() {
            @Override
            public void onResult(HashSet<String> strings, Throwable throwable) {
              // here I have to get all the Json Documents in the set and
              // make a whole json string

              result.complete(wholeJsonString); // <--resolves the future
            }
        });

  return result.get(); // <-- blocks until result.complete is called
}
Run Code Online (Sandbox Code Playgroud)

get()CompletableFuture 的方法还有一个带有超时参数的替代重载.我建议使用它来防止程序在由于某种原因未调用回调时累积挂起的线程.在try {块中实现整个回调也是一个好主意,并result.completefinally {块中执行以确保结果始终得到解决,即使回调期间出现意外错误也是如此.