Vaadin javascript扩展

时间:2015-05-22 02:27:45

标签: javascript ajax multithreading vaadin vaadin7

我正在尝试在javascript中编写一个简单的Vaadin扩展(意思是我的子类AbstractJavaScriptExtension),它会触发服务器端的方法调用。此方法调用将例如加载一些数据并更新组件的UI。基本上,我们的想法是为每个组件提供单次异步请求,目的是让服务器端长期运行的数据库/ Web服务调用并行运行。

由于我不需要不断更新组件,因此使用Vaadin Push会有点过分。我想使用普通的旧XHR。

所以我在我的扩展类中添加了一个javascript触发器函数,如下所示:

addFunction("trigger", jsonArray -> command.trigger());

(这是java 8语法,trigger()只是功能接口上的一种方法)

我尝试在我的javascript连接器中立即调用此触发器,如下所示:

window.com_example_AsyncTrigger = function () {
    this.trigger();
}

我编写了一个虚拟组件,使用Thread.sleep()模拟缓慢加载,并创建了三个实例,具有10,6和2秒延迟,同时记录加载的开始和结束时间戳。 然后,我使用我的扩展扩展了三个布局,以便在触发相应的触发器时添加每个组件。

当然,所有三个触发器都被触发,但它们在同一个请求中被触发(我可以从日志记录中看出它们是在单个服务器线程中执行的)。这意味着在大约18秒之后,所有3个组件一次更新,而我希望首先显示2秒组件,然后是6秒组件,最后是10秒组件,总时间约为10秒。

所以,我发现这一定是因为Vaadin在创建连接包装器时以某种方式将函数调用排队,并在单个请求上调用服务器端方法。所以我改变了我的javascript连接器实现,以异步方式调用客户端trigger()函数,如下所示:

window.com_example_AsyncTrigger = function () {
    var self = this;
    setTimeout(function() { self.trigger();}, 0);
}

当然,这些触发器现在会在单独的请求中触发,因为我可以从日志记录中看出工作线程的名称是不同的。 唯一的问题是......他们仍然按顺序运行。对self.trigger()的调用是快速连续完成的,但实际的XHR请求并不是并行完成的。下一个只在前一个完成后启动。

为什么会这样,我该如何解决它?

1 个答案:

答案 0 :(得分:2)

网络服务器不会并行处理来自同一客户端的请求,以防止出现任何竞争条件或锁定问题。要处理长时间运行的请求,您需要对处理请求的线程进行异步处理。完成后,使用UI.access(...)将结果写回UI。处理请求的线程将返回,并处理下一个请求。问题是,在客户端发送下一个请求之前,结果不会发送到服务器。但是所有长时间运行的请求都是并行处理的。

第一个选项:

定期轮询服务器(有一个vaadin插件)。结果将与下次投票一起发送。

第二个选项:

而不是轮询只使用推送。开销并不是那么大,如果你不期望同时有数百个用户,那应该不是问题。

进一步解释:

根据我对Vaadin框架的理解,它以下列方式处理请求:

  1. 处理从客户端发送的任何更改
  2. 致电您的听众(ValueChange,Click,...)
  3. 将更改发送到客户端
  4. 当第二个线程在第一个线程处于第三个步骤时更改URL时,这可能会导致严重问题,因为只有一半的更改将传输到客户端。当Vaadin检测到告诉您使用UI.access(...)时会抛出异常。 UI.access()负责直接执行提供的Runnable(当没有处理其他请求时)或在当前运行的请求完成后异步执行。 最后一点说明。锁是基于会话而不仅仅是基于UI。因此,对同一会话中不同UI的更改(例如,同一应用程序的不同选项卡)也会按顺序处理。