GWT中的同步RPC调用

Jas*_*son 9 java gwt jsni

(仅此标题应该让人们从木制品中走出来用棍棒打击我,但是听我说话).

我有一个用例,我需要从异步调用返回一个值.(我正在使用GWT-Platform,但概念是相同的.)我声明了最终的JavaScriptObject数组,然后在AsyncCallback中分配了值.但是,我需要返回值,并且该方法在AsyncCallback完成之前返回.因此,我需要以某种方式阻止,直到AsyncCallback完成.我需要在另一个方法中返回值,或者我只是在onSuccess()中执行我需要的操作.

我已经尝试过循环,定时器和其他一些没有运气的方法.有人可以帮忙吗?

@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];
}
Run Code Online (Sandbox Code Playgroud)

更新:根据要求,这是调用doGetWhereIAmMarker()的代码.我尝试使用Google Map对象(作为JavaScriptObject)作为参数使用单独的本机方法,但似乎在本机方法之间传递该对象会导致更新所述对象的能力.

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);
    });

}-*/;
Run Code Online (Sandbox Code Playgroud)

Ale*_*man 3

在某些时候,我不得不做类似的事情,但最终我消除了该代码,转而使用异步的东西。因此,我无法给出您需要使用的确切代码,但只能给出一些关于如何处理它的指示。

  • 首先,本博客介绍如何使用 javascript 进行同步 AJAX。
  • 其次,您必须提供对同步调用的支持。问题是GWT不支持提供同步AJAX调用的参数。最有可能的是他们不想鼓励它的使用。因此,您需要使用 JSNI 添加适当的方法XMLHttpRequest(您可能会扩展它),然后添加到RequestBuilder(也应该扩展它)。
  • 最后,使用扩展修改您的服务RequestBuilder。就像是

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

总而言之——来自同一篇博客文章(有点断章取义):

由于存在请求丢失和挂起浏览器的危险,因此不建议将同步 JavaScript 用于 (onbefore)unload 事件处理程序之外的任何内容。