伪造GWT同步RPC调用

首先,我知道做同步调用是“错误的”,并且知道“不可能”。

但是,在一个很复杂的情况下(我不知道如何解释),我需要等待服务器的响应,我使用GWT-Platform命令实现GWT RPC调用。

我正在寻找某种“黑客”来做这件事。

提前致谢。

有一个解决方案,但它并不容易(例如,您不能翻转单个参数使其工作)。 GWT正在使用普通的JS XMLHttpRequest。 在GWT中,有一个名为com.google.gwt.xhr.client.XMLHttpRequest的覆盖类型。 此类用于通过HTTP向服务器发送请求。 首先通过调用open方法初始化每个JS XMLHttpRequest。 此方法的参数很少,但第三个参数指定请求是否应该是异步的。 如果将其更改为false,则请求将是同步的。

但是GWT-RPC不直接使用这个类,它通过RpcRequestBuilder使用它,而且这个类也没有直接使用XMLHttpRequest,它使用的是RequestBuilder。

所以你需要做的是创建自定义版本的RpcRequestBuilder和RequestBuilder(它将使用XMLHttpRequest初始化为同步)。

您可以将RPCRequest构建器设置为GWT-RPC服务实例,方法是将其转换为ServiceDefTarget。

你还想要同步GWT-RPC请求吗?

通常,通过处理RPC请求的onSuccess()函数中的内容,您将自动“等待来自服务器的响应”。 所以我假设您要阻止当前运行的所有代码? 由于JavaScript是单线程的,并不容易,因此没有睡眠function可以暂停程序。

但是,使用计时器的黑客可能会做你想要的:

  Timer checkRPCResponse = new Timer() { @Override public void run() { if (!serverResponseReceived) { this.schedule(100); } else { proceedWithProgram(); } } }; checkRPCResponse.schedule(100); 

我没有尝试过如果this.schedule(100)在上面的例子中工作,但你明白了,这是检查服务器是否每100毫秒响应一次。 当然,您必须在onSuccess()函数中自己设置serverResponseReceived = true 。 在RPC之后立即调用计时器。

GWT调用XMLHttpRequest.open() whith为第三个参数,这意味着调用将是异步的。 我解决了类似的测试需求,只是强迫第三个参数始终为false:

 private static native void fakeXMLHttpRequestOpen() /*-{ var proxied = $wnd.XMLHttpRequest.prototype.open; (function() { $wnd.XMLHttpRequest.prototype.open = function() { arguments[2] = false; return proxied.apply(this, [].slice.call(arguments)); }; })(); }-*/; 

在调用fakeXMLHttpRequestOpen()之后 ,XMLHttpRequest的任何进一步使用将同步执行。 例如:

 remoteSvc.getResult(new AsyncCallback() { @Override public void onSuccess(String result) { GWT.log("Service called!"); } @Override public void onFailure(Throwable caught) { GWT.log("Service failed..."); } } GWT.log("Last message"); 

将总是渲染:

 Service called! Last message 

有关XMLHttpRequest.open()规范,请参阅https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open 。