且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Wicket调用冗长的操作并通过ajax进行更新

更新时间:2023-11-14 16:06:58

最简单的方法是让初始Ajax请求快速返回(没有任何结果)并添加 AjaxSelfUpdatingTimerBehavior 到目标组件。如果有结果,此行为将检查间隔(例如每10秒左右)。如果有结果,它应该更新组件并删除它自己。

The easiest way would be to have the initial Ajax request return fast (without any results) and add an AjaxSelfUpdatingTimerBehavior to the target component. This Behavior would then check an intervals (like every 10 seconds or so) if there's a result. If there's a result it should update the component ans remove itself.

这样你就可以在一个单独的任务中完成操作,而不会阻止你的Ajax调用。

This way you can do the operation in a separate task without blocking your Ajax calls.

为了详细说明,我创建了一个可运行的 quickstart 发出5个像你所描述的Ajax调用,每个调用在10秒到1分钟之间运行一段随机时间。同时,还有一个带有计数器的响应式AjaxLink。

To elaborate a bit, I created a runnable quickstart that issues 5 Ajax calls like you have described, each running a random amount of time between 10 seconds and one minute. At the same time, there is a responsive AjaxLink with a counter.

主要思想是将实际的Ajax调用与对慢速方法的调用分开。

The main idea is to separate the actual Ajax calls from the calls to the slow method.

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来完成工作(在你的情况下,在演示中只需要等待一段时间)。

As you can see, the label model doesn't directly call doSomeLengthyOperation() anymore. Instead a new Thread is spawned that does the heavy lifting. The Processor class just implements the Runnable interface and uses the run-method to do the work (in your case, in the demo it just waits some time).

getter对于PropertyModel封装此特技并使其透明,同时保持快速返回以防止阻塞。

The getter for the PropertyModel encapsulates this stunt and makes it transparent while allways returning fast to prevent blocking.

public String getResult() {
    String retValue;
    if (!processed) {
        retValue = String.format("Still busy after %d requests", counter++);
    } else {
        retValue = result;
    }
    return retValue;
}

处理过的成员只是一个标志,处理器使用它来指示它是什么完成等待(ehr working)。

The processed member is just a flag, that the Processor uses to indicate whe it's done waiting (ehr working).

由于你可能会同时发出超过5个线程,我建议使用某种Threadpool但是这超出了这个小演示的范围。

Since you'll probably issuing more than 5 Threads at the same time, I'd recommend to use some sort of Threadpool but that's beyond the scope of this little demo.

免责声明:这不是生产代码。它只是用于演示。它对你的资源不好,也不会优雅地处理它的缺乏。当用户点击重新加载或其他任何事情时,它将无法工作。

Disclaimer: This is no production code. It's just for demoing. It will not be nice to your resources nor will it handle any lack thereof gracefully. It will not work when the user hit's reload or anything else happens.