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



是否有方法在控制器外部使用await()机制?

我不希望代码在控制器中进行异步调用,而是将代码放在可以被多个控制器重用的服务类中。然而,没有办法在控制器外部调用await,因为该方法是受保护的。

例如在控制器中:
   ServiceClass service = new My ServiceClass();
   MyObject myObject= service.getMeAnObject();
   render(myObject);

和服务类:

   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);
      }
      ...
   }

有办法实现这样的事情吗?

谢谢你的帮助。


Edit:我遵循Pere的建议,让服务类实现Controller,但是它可以工作,有必要对使用它的控制器进行增强。我发现完成这一任务的唯一方法是至少在调用控制器类中调用一次await方法()。

但是,我仍然没有验证代码实际上是挂起的。


编辑2:我从google组得到的一个建议是,我应该真正尝试在控制器中执行await,所以也许更好的解决方案是让服务返回a承诺并让控制器等待这个,但是我没办法这么做,是吗?

例如在控制器中:
  ServiceClass service = new My ServiceClass(); 
  Promise<MyObject> promise = service.getMeAnObject(); 
  MyObject myObject = await(promise); 
  render(myObject); 

和服务类:

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

}

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

我已经采取了在WSAsync中播放的例子。WSAsyncRequest类,这似乎有效。

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

在控制器中:

ServiceClass service = new My ServiceClass(); 
Promise<MyObject> promise = service.getMeAnObject(); 
MyObject myObject = await(promise); 
render(myObject); 

和服务类:

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); 
        } 
    } 
}

这似乎解决了我现在的问题。

谢谢。

正如您提到的await只能从控制器访问。

让Service类扩展Controller,在其中创建一些受保护的支持方法,并将其用作Controller的父类。

这样你就可以在控制器之间共享实现,同时可以访问所有的控制器方法(await, render等)

这可能太迟了,无法帮助你:),但方法是通过使用promise . onredeem()方法调用一个新的承诺,返回并等待在控制器中…

public Promise<Boolean> deauthorise() {
    final Promise<Boolean> promise = new Promise<>();
    WS.url("https://connect.stripe.com/oauth/deauthorize")
            .setParameter("client_secret", play.Play.configuration.getProperty("stripe.secretKey"))
            .setParameter("client_id", play.Play.configuration.getProperty("stripe.clientId"))
            .setParameter("stripe_user_id", this.stripeUserId)
            .postAsync()
            .onRedeem(new Action<Promise<HttpResponse>>() {
                @Override
                public void invoke(Promise<HttpResponse> result) {
                    HttpResponse response = result.getOrNull();
                    promise.invoke(response != null && response.success());
                }
            });
    return promise;
}

最新更新