2011-09-08 10 views
8

(Ese título solo debería hacer que las personas salgan de la obra de madera para golpearme con palos, pero escúchenme).Llamadas RPC síncronas en GWT

Tengo un caso de uso en el que necesito devolver un valor de una llamada asincrónica. (Estoy usando GWT-Platform, pero los conceptos son los mismos.) Decidí una matriz final de JavaScriptObject, luego asigné el valor dentro de AsyncCallback. Sin embargo, debo devolver el valor y el método regresa antes de que se complete el AsyncCallback. Por lo tanto, tengo que bloquear de alguna manera hasta que se complete el AsyncCallback. Necesito el valor devuelto en otro método, o simplemente hago lo que necesito en onSuccess().

He intentado bucles, temporizadores y algunos otros métodos sin suerte. ¿Alguien puede ayudar?

@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]; 
} 

ACTUALIZACIÓN: Como se pide, aquí está el código que llama doGetWhereIAmMarker(). Intenté tener un método nativo independiente con el objeto Google Map (como JavaScriptObject) como parámetro, pero parece que pasar ese objeto entre métodos nativos elimina la capacidad de actualizar dicho objeto.

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

¿Puedes mostrar un poco más de código? Estoy interesado en las partes que llaman a este código, y también las partes que consumen JavaScriptObject que se devuelve desde 'doGetWhereAmIMarker (...)'. –

+0

Se agregó el método nativo de llamada. GoogleMapUtil está en https://github.com/dartmanx/mapmaker/blob/master/src/main/java/org/jason/mapmaker/client/util/GoogleMapUtil.java, pero no está comprometido con el método createMarker() .Sin embargo, es similar al método createMarkerArray(). – Jason

+0

¿Por qué no funciona si pones un rato (asyncIsDone) {sleep}. que parece ser lo más simple de hacer ... o hacer que sea para() {dormir} que continuará después de que haya pasado un cierto tiempo? – Rohan

Respuesta

3

En algún momento tuve que hacer algo similar pero finalmente eliminé ese código a favor de las cosas asincrónicas. Por lo tanto, no puedo dar el código exacto que necesita usar, pero solo algunos consejos sobre cómo abordarlo.

  • En primer lugar, this blog describe cómo hacer AJAX sincrónico usando javascript.
  • En segundo lugar, debe proporcionar soporte para llamadas de sincronización. El problema es que GWT no admite el parámetro que proporciona llamadas AJAX sincrónicas. Lo más probable es que no quieran alentar su uso. Por lo tanto, necesitaría usar JSNI para agregar el método apropiado al XMLHttpRequest (que probablemente extendería) y luego al RequestBuilder (también debería extenderlo).
  • Finalmente, modifique su servicio utilizando RequestBuilder extendido. Algo así como

((ServiceDefTarget) servicio) .setRpcRequestBuilder (RequestBuilder);

Y en conclusión - de la misma entrada del blog (un poco fuera de contexto):

Debido al peligro de una solicitud perderse y pasar el navegador, Javascript síncrona no está recomendado para cualquier cosa fuera de (antes) descarga controladores de eventos.

+0

He hecho AJAX manual sincrónico antes, pero como esto es GWT, estoy atascado con las limitaciones de GWT. Estoy usando DispatchAsync de GWT-Platform para obtener datos, y no veo nada allí usando RequestBuilder. – Jason

+1

Debería poder usar cualquier código Javascript con GWT usando JSNI. 'RequestBuilder' se usa internamente cuando trabajas con RPC. Una vez que tenga su servicio, puede asignar su 'RequestBuilder' personalizado utilizando el fragmento que proporcioné. –

+0

Voy a aceptar tu respuesta, ya que es interesante y podría ser algo que deba probar algún día. Sin embargo, encontré la respuesta a mi problema original que me impedía usar la solicitud asincrónica. – Jason

0

Creo que es toda suerte ....
No podemos hacer en Gwt para captar la respuesta y enviarla, porque inmediatamente después de la solicitud se envía al siguiente método comienza a ejecutar, ni molestar a la respuesta Aún no obstante nos satisfacen para usar los temporizadores, es lo que creo ...

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