GWT/Java 中等待多个异步事件完成的干净方法
在 Java 中等待多个异步回调函数完成然后再继续的最佳方法是什么?具体来说,我将 GWT 与 AsyncCallback 一起使用,但我认为这是一个普遍问题。这就是我现在所拥有的,但肯定有更干净的方法......
AjaxLoader.loadApi("books", "0", new Runnable(){
public void run() {
bookAPIAvailable = true;
ready();
}}, null);
AjaxLoader.loadApi("search", "1", new Runnable(){
public void run() {
searchAPIAvailable = true;
ready();
}}, null);
loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {
public void onSuccess(LoginInfo result) {
appLoaded = true;
ready();
}
});
private void ready() {
if(bookAPIAvailable && searchAPIAvailable && appLoaded) {
// Everything loaded
}
}
What is the best way to wait for multiple asynchronous callback functions to finish in Java before continuing. Specifically I'm using GWT with AsyncCallback, but I think this is a generic problem. Here's what I have now, but surely there is cleaner way...
AjaxLoader.loadApi("books", "0", new Runnable(){
public void run() {
bookAPIAvailable = true;
ready();
}}, null);
AjaxLoader.loadApi("search", "1", new Runnable(){
public void run() {
searchAPIAvailable = true;
ready();
}}, null);
loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {
public void onSuccess(LoginInfo result) {
appLoaded = true;
ready();
}
});
private void ready() {
if(bookAPIAvailable && searchAPIAvailable && appLoaded) {
// Everything loaded
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我在我的项目中编写了两个类来解决这个问题。基本上,每个单独的回调都会向父级注册。父级等待每个子级回调完成,然后触发它自己的handleSuccess()。
客户端代码如下所示:
I wrote two classes that solve this problem on my project. Basically, each individual callback registers with a parent. The parent waits for each child callback to complete, then fires off it's own handleSuccess().
The client code looks like this:
就像 @Epsen 所说,
Future
可能就是您想要的。不幸的是,我不相信Future
与 GWT 兼容。不过,gwt-async-future 项目声称将此功能引入 GWT我从来没有尝试过。也许值得一看。Like @Epsen says,
Future
is probably what you want. Unfortunately, I don't believeFuture
s are GWT-compatible. The gwt-async-future project claims to bring this functionality to GWT, though I've never tried it. It may be worth a look.我自己也一直在努力解决这个问题,并且我使用了几种方法 - “链”方法变得丑陋(但如果您为每个方法创建类而不是内联类,则可以改进)。
您自己版本的一个变体对我来说效果很好:
我所做的就是为我要执行的调用次数创建一个计数器,然后每个异步结果调用
ready()
(请务必执行失败方法上也是如此,除非您打算做一些不同的事情)在就绪方法中,我递减计数器并查看是否仍有未完成的调用。
它仍然很丑陋,但它可以让您根据需要添加调用。
I've struggled with this myself, and I've used several methods- the 'chain' one just gets ugly (but can be improved if you create classes instead of inline classes for each method).
A variant of your own version works well for me:
All I did was create a counter for the number of calls I'm going to do, then each async result calls
ready()
(be sure to do this on the failure methods too, unless you're going to do something different)In the ready method, I decrement the counter and see if there are still outstanding calls.
It's still ugly, but it lets you add calls as needed.
首先也是最重要的 - 永远不要陷入这种情况。重新设计您的 RPC 服务,使每个用户流/屏幕最多需要一次 RPC 调用才能工作。在这种情况下,您对服务器进行了三个调用,这只是浪费带宽。延迟只会杀死你的应用程序。
如果您不能并且确实需要破解,请使用 计时器 定期轮询所有数据是否已下载。您在上面粘贴的代码假设 login() 方法将是最后完成的 - 这是错误的。它可能是第一个完成的,然后你的应用程序将处于不确定状态 - 这非常难以调试。
First and foremost - don't ever get into such a situation. Redesign your RPC services such that every user flow/screen requires at most a single RPC call to work. In this case, you are making three calls to the server, and its just a waste of bandwidth. The latency will just kill your app.
If you can't and really need a hack, use a Timer to periodically poll if all data has downloaded. The code you pasted above assumes login() method will be the last to finish - which is wrong. Its may be the first to finish, and then your app will be in an indeterminate state - which is very difficult to debug.
只是提出一些想法:
回调使用 HandlerManager 触发一些 GwtEvent。
包含就绪方法的类在 HandlerManager 中注册为回调方法触发的事件的 EventHandler,并保存状态(bookAPIAvailable、searchAPIAvailable、appLoaded)。
当事件到达时,特定状态会发生更改,我们检查所有状态是否都符合预期。
有关使用 GWTEvent、HandlerManager 和 EventHandler 的示例,请参阅 http://www.webspin.be/? p=5
Just tossing up some ideas:
The callbacks fire some GwtEvent using the HandlerManager.
The class containing the ready methods is registered with the HandlerManager as an EventHandler for the events fired by the callback methods, and holds the state (bookAPIAvailable, searchAPIAvailable, appLoaded).
When a event arrives that specific state is changed, and we check if all the states are as desired.
For an example using the GWTEvent, HandlerManager and EventHandler, see http://www.webspin.be/?p=5
我做了类似于@Sasquatch的事情,但使用了“CallbackCounter”对象:
然后在我的回调中我只需调用:
I did something similar to @Sasquatch, but instead making use of a "CallbackCounter" object:
Then in my callback I just call:
正如 sri 所说,最好的情况是重新设计您的应用程序,一次只调用一次后端。这避免了这种情况,并保留了带宽和延迟时间。在网络应用程序中,这是您最宝贵的资源。
话虽如此,GWT RPC 模型并不能真正帮助您以这种方式组织事物。我自己也遇到过这个问题。我的解决方案是实现一个计时器。计时器将每隔 X 秒轮询您的结果,当检索到所有预期结果时,您的执行流程可以继续。
<代码>
Best case scenario, as sri said, is to redesign your app to only call the backend once at a time. This avoids this kind of scenario, and preserves bandwidth and latency time. In a web app, this is your most precious resource.
Having said that the GWT RPC model doesn't really help you to organize things in this manner. I've run into this problem myself. My solution was to implement a timer. The timer will poll your results every X seconds, and when all your expected results are retrieved, your execution flow can continue.
理想情况下,您希望按照其他发帖者所述进行操作,并在单个异步调用中尽可能多地执行操作。有时您必须进行一系列单独的调用。方法如下:
您想要链接异步调用。当最后一个异步完成(登录)时,所有项目都会加载。
干杯,
--拉斯
Ideally, you want to do as other posters have stated and do as much as you can in a single async call. Sometimes you have to do a bunch of separate calls. Here's how:
You want to chain the async calls. When the last async completes (login), all the items are loaded.
Cheers,
--Russ