异步WS调用和控制器外的await()

Dan*_*aty 8 playframework

有没有办法在控制器外部使用await()机制?

我不希望代码在控制器中进行异步调用,而是将该代码放在可由多个控制器重用的服务类中,但是,由于该方法受到保护,因此无法在控制器外调用等待.

例如在控制器中:

   ServiceClass service = new My ServiceClass();
   MyObject myObject= service.getMeAnObject();
   render(myObject);
Run Code Online (Sandbox Code Playgroud)

和服务类:

   public class ServiceClass
   {
      ...
      public MyObject getMeAnObject()
      {
         String url = "http://...";
         Promise<HttpResponse> promise = url(url).getAsync();

         // do something here similar to await in a controller
         // that suspends the code waiting for the response
         // to be retrieved

         HttpResponse response = promise.get();
         return buildMyObjectFromResponse(reponse);
      }
      ...
   }
Run Code Online (Sandbox Code Playgroud)

有没有办法实现这样的目标?

谢谢你的帮助.


编辑:我遵循Pere的建议,并使服务类实现Controller,但是它有效,必须增强使用它的控制器.我发现完成这项工作的唯一方法是至少在调用控制器类中调用await方法().

但是,我仍然没有验证代码实际上是暂停的.


编辑2:我从google小组获得的一个建议是我应该尝试在控制器中进行等待,所以也许更好的解决方案是让服务返回Promise并让控制器等待这个然后就没有了我的方式是todo吗?

例如在控制器中:

  ServiceClass service = new My ServiceClass(); 
  Promise<MyObject> promise = service.getMeAnObject(); 
  MyObject myObject = await(promise); 
  render(myObject); 
Run Code Online (Sandbox Code Playgroud)

和服务类:

  public class ServiceClass 
  { 
     ... 
     public Promise<MyObject> getMeAnObject() 
     { 
        String url = "http://..."; 
        // Somehow Build a Promise<MyObject> 
     } 
     ... 
  } 
Run Code Online (Sandbox Code Playgroud)

}

Dan*_*aty 3

到目前为止,这是我认为最好的方法,除非在 Play 实例中管理单独的线程池存在问题。

我已经举例说明了 Play 在 WSAsync.WSAsyncRequest 类中所做的事情,这似乎有效。

本质上,等待是在控制器内完成的,但是服务类返回我期望服务返回的对象的 Promise,这很好,因为我不知道如何在控制器级别检索该对象的详细信息。

在控制器中:

ServiceClass service = new My ServiceClass(); 
Promise<MyObject> promise = service.getMeAnObject(); 
MyObject myObject = await(promise); 
render(myObject); 
Run Code Online (Sandbox Code Playgroud)

以及服务等级:

public class ServiceClass 
{ 
    public Promise<MyObject> getMeAnObject() 
    { 
        String url = "http://..."; 
        return execute(WS.url(url).getAsync()); 
    } 

    private Promise<MyObject> execute(final Promise<HttpResponse> promise) 
    { 
        try 
        { 
            final Promise<MyObject> smartFuture = new Promise<MyObject>(); 
            ScheduledThreadPoolExecutor executor = MyAppThreadPools.getServiceThreadPool(); 

            executor.submit(new Runnable() 
                { 
                    @Override 
                    public void run() 
                    { 
                        try 
                        { 
                            smartFuture.invoke(new MyObject(promise.get())); 
                        } 
                        catch (Throwable e) 
                        {                
                            smartFuture.invokeWithException(e); 
                        } 
                    } 
                });

            return smartFuture; 
        } 
        catch (Exception e) 
        { 
            throw new RuntimeException(e); 
        } 
    } 
}
Run Code Online (Sandbox Code Playgroud)

所以这似乎暂时解决了我的问题。

谢谢大家。