GWT中的同步RPC调用 [英] Synchronous RPC Calls in GWT

查看:225
本文介绍了GWT中的同步RPC调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个用例,其中I需要从异步调用中返回一个值。 (我正在使用GWT平台,但概念是相同的。)我声明了一个最终的JavaScriptObject数组,然后在AsyncCallback中分配值。但是,我需要返回该值,并且该方法在AsyncCallback完成之前返回。因此,我需要阻止,直到AsyncCallback完成。我需要在另一个方法中返回的值,或者我只是在onSuccess()中做我需要的。



我已经尝试过循环,定时器和一些其他方法没有运气。任何人都可以帮忙吗?
$ b $ pre $ @Override
public JavaScriptObject doGetWhereAmIMarker(final double lng,final double lat){

final JavaScriptObject [] markerArray = new JavaScriptObject [1]; //获知位置描述结果>(){
@Override
public void onFailure(Throwable caught){
capture.printStackTrace();
}

@Override
public void onSuccess(GetLocationDescriptionsResult result){
Map< String,Location> resultMap = result。 getResult();
StringBuffer message = new StringBuffer(); $ b $ for(String key:resultMap.keySet()){
message.append(key).append(:)。 append(\ n);
}

映射tempMap = new HashMap();
tempMap.put(TITLE ,Location Information);
tempMap.put(LAT,lat);
tempMap.put(LNG,lng);
tempMap.put(CONTENTS, message.toString());

JavaScriptObj ect marker = GoogleMapUtil.createMarker(tempMap);
markerArray [0] = marker;
if(markerArray [0]!= null){
GWT.log(Marker Array Updated);
}

}
});

return markerArray [0];




$ b $ p更新:根据要求,这里是调用doGetWhereIAmMarker()的代码。我尝试过使用Google Map对象(作为JavaScriptObject)作为参数的独立本地方法,但似乎在本地方法之间传递该对象会导致更新所述对象。

  public native void initMap(JavaScriptObject mapOptions,JavaScriptObject bounds,JavaScriptObject border,JsArray markerArray,Element e)/ *  -  {

// create地图并将其放在给定范围内
map = new $ wnd.google.maps.Map(e,mapOptions);
if(bounds!= null){
map.fitBounds(bounds);


//为边界设置多边形
if(border!= null){
border.setMap(map);
}

//设置信息窗口
if(markerArray!= null&&& markerArray.length> 0){
var infoWindow = new $ wnd.google.maps.InfoWindow({
content:InfoWindow Content Goes Here
});

for(var i = 0; i< markerArray.length; i ++){
var marker = markerArray [i];
marker.setMap(map);
$ wnd.google.maps.event.addListener(marker,'click',function(){
infoWindow.setContent(marker.content);
infoWindow.open(map,this) ;
});



//需要引用function()中的调用类,因此设置对this的引用
var that = this;

$ wnd.whereAmI = function(lng,lat){
that。@ org.jason.mapmaker.client.view.MapmakerMapViewImpl :: whereAmI(DD)(lng,lat);


$ wnd.google.maps.event.addListener(map,'click',function(event){
var lat = event.latLng.lat();
var lng = event.latLng.lng();
$ wnd.whereAmI(lng,lat);
});

} - * /;


解决方案

在某些时候,我不得不做类似的事情,但最终我消除了那些代码以支持异步的东西。因此,我无法提供您需要使用的确切代码,只能指出如何处理这些代码。




  • 首先,这个博客描述了如何使用javascript来实现同步AJAX。

  • 其次,您必须提供对同步呼叫的支持。问题是GWT不支持提供同步AJAX调用的参数。最有可能的是他们不想鼓励它的使用。因此,您需要使用JSNI将适当的方法添加到 XMLHttpRequest (您可能会扩展),然后添加到 RequestBuilder (也应扩展它)。
  • 最后,使用扩展 RequestBuilder 修改您的服务。类似于




((ServiceDefTarget)服务).setRpcRequestBuilder(requestBuilder);


最后 - 从相同的博客文章(稍微超出上下文):


由于请求丢失和挂起浏览器的危险,
同步javascript不推荐用于
(onbefore)卸载事件处理程序之外的任何内容。



(That title alone should cause people to come out of the woodwork to bash me with clubs, but hear me out).

I have a use case where I need to return a value from a asynchronous call. (I'm using GWT-Platform, but the concepts are the same.) I declared a final JavaScriptObject array, then assigned the value within the AsyncCallback. However, I need to return the value, and the method returns before the AsyncCallback completes. Therefore, I need to block somehow until the AsyncCallback completes. I need the returned value in another method, or I'd just do what I need to in onSuccess().

I've tried loops, Timers, and a few other methods with no luck. Can anyone help?

@Override
public JavaScriptObject doGetWhereAmIMarker(final double lng, final double lat) {

    final JavaScriptObject[] markerArray = new JavaScriptObject[1];  // ugly hack, I know
    dispatch.execute(new GetLocationDescriptionsAction(lng, lat), new AsyncCallback<GetLocationDescriptionsResult>() {
        @Override
        public void onFailure(Throwable caught) {
            caught.printStackTrace();
        }

        @Override
        public void onSuccess(GetLocationDescriptionsResult result) {
            Map<String, Location> resultMap = result.getResult();
            StringBuffer message = new StringBuffer();
            for (String key : resultMap.keySet()) {
                message.append(key).append(": ").append(resultMap.get(key)).append("\n");
            }

            Map tempMap = new HashMap();
            tempMap.put("TITLE","Location Information");
            tempMap.put("LAT", lat);
            tempMap.put("LNG", lng);
            tempMap.put("CONTENTS", message.toString());

            JavaScriptObject marker = GoogleMapUtil.createMarker(tempMap);
            markerArray[0] = marker;
            if (markerArray[0] != null) {
                GWT.log("Marker Array Updated");
            }

        }
    });

    return markerArray[0];
}

UPDATE: As requested, here is the code that calls doGetWhereIAmMarker(). I've tried having a separate native method with the Google Map object (as a JavaScriptObject) as a parameter, but it appears that passing that object between native methods kills the ability to update said object.

public native void initMap(JavaScriptObject mapOptions, JavaScriptObject bounds, JavaScriptObject border, JsArray markerArray, Element e) /*-{

    // create the map and fit it within the given bounds
    map = new $wnd.google.maps.Map(e, mapOptions);
    if (bounds != null) {
        map.fitBounds(bounds);
    }

    // set the polygon for the borders
    if (border != null) {
        border.setMap(map);
    }

    // set up the info windows
    if (markerArray != null && markerArray.length > 0) {
        var infoWindow = new $wnd.google.maps.InfoWindow({
            content:"InfoWindow Content Goes Here"
        });

        for (var i = 0; i < markerArray.length; i++) {
            var marker = markerArray[i];
            marker.setMap(map);
            $wnd.google.maps.event.addListener(marker, 'click', function() {
                infoWindow.setContent(marker.content);
                infoWindow.open(map, this);
            });
        }
    }

    // need to reference the calling class inside the function(), so set a reference to "this"
    var that = this;

   $wnd.whereAmI=function(lng, lat) {
        that.@org.jason.mapmaker.client.view.MapmakerMapViewImpl::whereAmI(DD)(lng,lat);
   }

    $wnd.google.maps.event.addListener(map, 'click', function(event) {
        var lat = event.latLng.lat();
        var lng = event.latLng.lng();
        $wnd.whereAmI(lng, lat);
    });

}-*/;

解决方案

At some point I had to do something similar but eventually I eliminated that code in favor of asynchronous stuff. Therefore, I can't give exact code that you need to use but only few pointers on how to approach it.

  • Firstly, this blog describes how to do synchronous AJAX using javascript.
  • Second, you must provide support for sync calls. The problem is that GWT does not support the parameter that provides synchronous AJAX calls. Most likely is that they don't want to encourage its use. Therefore you would need to use JSNI to add appropriate method to XMLHttpRequest (which you probably would extend) and then to RequestBuilder (also should extend it).
  • Finally, amend your service using extended RequestBuilder. Something like

((ServiceDefTarget)service).setRpcRequestBuilder(requestBuilder);

And in conclusion - from the same blog post (slightly out of context):

Because of the danger of a request getting lost and hanging the browser, synchronous javascript isn't recommended for anything outside of (onbefore)unload event handlers.

这篇关于GWT中的同步RPC调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆