基于这个SO question,我已经了解到Wicket将后续的AJAX请求排队。现在我的页面上有几个AJAX请求,我想再添加一个产生冗长操作的页面。
public void populateItem(final Item item) {
final MyObject object = (MyObject) item.getModelObject();
// ... a couple of fields
Label statusLabel = new Label("status", new AbstractReadOnlyModel() {
@Override
public Object getObject() {
return someService.doSomeLengthyOperation();
}
});
statusLabel.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(5)));
item.add(statusLabel)
}
一旦这个Ajax请求触发,它可能需要一分钟才能完成执行。这里的问题是someService.doSomeLengthyOperation()
将会执行n times the number of rows
,这意味着我将排队n times two-minutes
。现在,正如我所提到的,Wicket将后续的AJAX请求排队。
我需要number-of-rows * minutes-it-take-to-finish-the-operation
加载页面或做其他需要AJAX的东西
new AjaxButton("ajax-button"){
@Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
//.. this won't be executed until all the statusLabels have finished invoking getObject()
}
}
我想避免创建一个公开我的服务并且必须编写自己的AJAX调用的Web服务。我有什么选择? (使用Wicket 1.5 / Pax-Wicket)
答案 0 :(得分:3)
最简单的方法是让初始Ajax请求快速返回(没有任何结果)并向目标组件添加AjaxSelfUpdatingTimerBehavior。如果有结果,此行为将检查间隔(例如每10秒左右)。如果有结果,它应该更新组件并删除它自己。
这样,您可以在单独的任务中执行操作,而不会阻止Ajax调用。
为了详细说明,我创建了一个可运行的quickstart,它可以像你所描述的那样发出5个Ajax调用,每个调用运行10秒到1分钟之间的随机时间。与此同时,还有一个带有计数器的响应式AjaxLink。
主要思想是将实际的Ajax调用与对慢速方法的调用分开。
add(new ListView<DataHolder>("list", list) {
@Override
protected void populateItem(ListItem<DataHolder> item) {
DataHolder dh = item.getModelObject();
item.add(new Label("itemNumber", new PropertyModel<Integer>(dh, "number")));
Label result = new Label("itemResult", new PropertyModel<String>(dh, "result"));
result.setOutputMarkupId(true);
result.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(2)));
item.add(result);
Thread thread = new Thread(new Processor(item.getModelObject()));
thread.start();
}
});
如您所见,标签模型不再直接调用doSomeLengthyOperation()
。相反,会产生一个新的线程来完成繁重的工作。 Processor类只是实现Runnable接口并使用run-method来完成工作(在你的情况下,在演示中它只是等待一段时间)。
PropertyModel的getter封装了这个特技并使其透明,同时快速返回以防止阻塞。
public String getResult() {
String retValue;
if (!processed) {
retValue = String.format("Still busy after %d requests", counter++);
} else {
retValue = result;
}
return retValue;
}
处理后的成员只是一个标志,处理器用它来表示它已经完成等待(ehr工作)。
由于您可能会同时发出超过5个线程,我建议使用某种Threadpool,但这超出了这个小型演示的范围。
免责声明:这不是生产代码。它只是用于演示。它对你的资源不好,也不会优雅地处理它的缺乏。当用户点击重新加载或其他任何事情时,它将无法工作。
答案 1 :(得分:0)
我不完全确定WicketStuff异步任务是否可以帮助您,但尝试一下:
https://github.com/wicketstuff/core/wiki/Async-tasks
以下是Async Tasks项目中的简短演示:
public class DemoPage extends WebPage implements IRunnableFactory {
public DemoPage() {
Form<?> form = new Form<Void>("form");
AbstractTaskContainer taskContainer = DefaultTaskManager.getInstance()
.makeContainer(1000L, TimeUnit.MINUTES);
ProgressButton progressButton = new ProgressButton("button", form,
Model.of(taskContainer), this, Duration.milliseconds(500L));
ProgressBar progressBar = new ProgressBar("bar", progressButton);
add(form);
form.add(progressButton);
form.add(progressBar);
}
@Override
public Runnable getRunnable() {
return new IProgressObservableRunnable() {
// Runnable implementation.
};
}