是否有方法在控制器外部使用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;
}