Синхронные вызовы RPC в GWT - PullRequest
       1

Синхронные вызовы RPC в GWT

9 голосов
/ 08 сентября 2011

(Одно это название должно заставить людей выйти из дерева, чтобы избивать меня дубинками, но выслушать меня).

У меня есть случай, когда мне нужно вернуть значение из асинхронного вызова. (Я использую 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];
}

ОБНОВЛЕНИЕ: по запросу, вот код, который вызывает 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);
    });

}-*/;

Ответы [ 2 ]

3 голосов
/ 09 сентября 2011

В какой-то момент мне пришлось сделать что-то подобное, но в конце концов я удалил этот код в пользу асинхронных вещей. Поэтому я не могу дать точный код, который вам нужно использовать, но лишь несколько указаний о том, как к нему подойти.

  • Во-первых, этот блог описывает, как сделать синхронный AJAX с помощью JavaScript.
  • Во-вторых, вы должны обеспечить поддержку синхронизации вызовов. Проблема в том, что GWT не поддерживает параметр, который обеспечивает синхронные вызовы AJAX. Скорее всего, они не хотят поощрять его использование. Поэтому вам нужно будет использовать JSNI для добавления соответствующего метода к XMLHttpRequest (который вы, вероятно, расширили бы), а затем к RequestBuilder (также должен его расширить).
  • Наконец, измените ваш сервис, используя расширенный RequestBuilder. Что-то вроде

((ServiceDefTarget) сервис) .setRpcRequestBuilder (requestBuilder);

И в заключение - из того же поста в блоге (немного вне контекста):

Из-за опасности потери запроса и зависания браузера, синхронный JavaScript не рекомендуется для чего-либо за пределами (onbefore) выгрузить обработчики событий.

0 голосов
/ 27 сентября 2013

Думаю, это вся судьба ....
Мы не можем сделать в Gwt перехват ответа и его отправку, потому что сразу после отправки запроса начинает выполняться следующий метод, который не беспокоит ответ Тем не менее, однако, они удовлетворяют нас, чтобы использовать Таймеры, это то, что я думаю ...

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