2011-09-08 58 views
8

(单单这个标题应该会导致人们走出木制工具来打扰我与俱乐部,但听我说)。GWT中的同步RPC调用

我有一个用例,我需要从异步调用中返回一个值。 (我正在使用GWT平台,但概念是相同的。)我声明了一个最终的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]; 
} 

更新:根据要求,这里是调用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) { 
     [email protected]::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); 
    }); 

}-*/; 
+0

你能展示一些更多的代码吗?我对调用此代码的部分以及使用从'doGetWhereAmIMarker(...)'返回的JavaScriptObject的部分感兴趣。 –

+0

添加了调用本机方法。 GoogleMapUtil位于https://github.com/dartmanx/mapmaker/blob/master/src/main/java/org/jason/mapmaker/client/util/GoogleMapUtil.java,但未提交createMarker()方法。但是,它与createMarkerArray()方法类似。 – Jason

+0

为什么它不起作用,然后如果你只是把一段时间(asyncIsDone){睡眠}。这似乎是最简单的事情......或者让它成为一个for(){sleep},在一段时间过去后它会继续? – Rohan

回答

3

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

  • 首先,this blog描述了如何使用javascript来实现同步AJAX。
  • 其次,您必须支持同步呼叫。问题是GWT不支持提供同步AJAX调用的参数。最有可能的是他们不想鼓励它的使用。因此,您需要使用JSNI为XMLHttpRequest(您可能会扩展)和RequestBuilder(也应扩展它)添加适当的方法。
  • 最后,使用扩展RequestBuilder修改您的服务。像

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

和结束 - 从相同的博客文章(略断章取义):

因为请求的危险迷路和悬挂的浏览器,不建议 同步的JavaScript任何超出 (onbefore)卸载事件处理程序。

+0

我之前已经完成了手动同步AJAX,但是由于这是GWT,我被GWT的限制所困。我正在使用GWT-Platform的DispatchAsync获取数据,并且我没有看到使用RequestBuilder的任何内容。 – Jason

+1

您应该可以使用任何使用JSNI的GWT的Javascript代码。当您处理RPC时,内部使用“RequestBuilder”。一旦你有了你的服务,你可以使用我提供的代码片段来分配你自定义的'RequestBuilder'。 –

+0

我会接受你的答案,因为它很有趣,可能是我有一天需要尝试的东西。但是,我发现原来的问题的答案阻止了我使用异步请求。 – Jason

0

我觉得一切都命运....
我们不能在GWT做赶上响应并发送,因为后立即请求发送下一方法开始执行,但也不打扰响应 仍他们满足我们使用定时器,是我认为...

Timer t = new Timer() { 
     @Override 
     public void run() { 
     Window.alert("Nifty, eh?"); 
     } 
    }; 
    t.schedule(5000);