2016-05-12 12 views
9

Wyświetlam mapę pogodową w aplikacji GWT. Używam GWT 2.7 i opakowania GWT API API GoogleMaps dostępnego pod numerem here (gwt-maps-3.8.0-pre1.zip).Odświeżający serwer kafli GoogleMaps działa w JavaScript, ale nie w GWT

Używam serwera kaflowego do pobierania prognozy pogody co 5 minut. Po 5 minutach odświeżam mapę, ustawiając zoom na 1, a następnie z powrotem do oryginału, uruchamiając zmianę rozmiaru i usuwając, a następnie ponownie dodając warstwę meteorologiczną.

To zadziałało dobrze. Jednak ostatnio zauważyłem, że to już nie działa: odświeżanie nigdy nie idzie nawet do serwera kafelków, więc nie wyświetla się nowa pogoda. Jeśli opuścisz moją mapę o 12 godzin, zobaczysz pogodę, która ma 12 godzin. Wcześniej mapa była automatycznie aktualizowana. Nie zmieniłem żadnego z moich kodów. Domyślam się, że coś zmieniło się w bazowym interfejsie API JavaScript GoogleMaps.

Jednak potem stworzył ten prosty przykład JavaScriptu czystego:

<!DOCTYPE html> 
<html> 
    <head> 
     <title>Map Test</title> 
     <style type="text/css"> 
      html, body { height: 100%; margin: 0; padding: 0; } 
      #map { 
       width:90%; 
       height: 90%; 
       display:inline-block; 
      } 
     </style> 
    </head> 
<body> 
<div id="map"></div> 
<button type="button" onClick="refreshMap()">Refresh</button> 
<script type="text/javascript"> 

    var map; 
    var tileNEX; 

    function initMap() { 

     var mapOptions = { 
      zoom: 8, 
      center: new google.maps.LatLng(42.5, -95.5), 
      mapTypeId: google.maps.MapTypeId.ROADMAP 
     }; 

     map = new google.maps.Map(document.getElementById('map'), mapOptions); 

     tileNEX = new google.maps.ImageMapType({ 
      getTileUrl: function(tile, zoom) { 
       return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/" + zoom + "/" + tile.x + "/" + tile.y +".png?"+ (new Date()).getTime(); 
      }, 
      tileSize: new google.maps.Size(256, 256), 
      opacity:0.60, 
      name : 'NEXRAD', 
      isPng: true 
     }); 

     map.overlayMapTypes.setAt("0",tileNEX); 
    } 

    function refreshMap(){ 
     var zoom = map.getZoom(); 
     map.setZoom(1); 
     map.setZoom(zoom); 

     //google.maps.event.trigger(map, 'resize'); 

     //var layer = map.overlayMapTypes.getAt(0); 
    //map.overlayMapTypes.setAt(0, null); 
    //map.overlayMapTypes.setAt(0, layer); 
    } 

</script> 
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"> 
</script> 
</body> 
</html> 

Ku mojemu zaskoczeniu, to nadal działa dobrze. Po kliknięciu przycisku Odśwież mapa przechodzi do serwera kafelków i pobiera nowe kafelki.

Więc próbowałem robić dokładnie to samo w GWT:

package com.example.client; 

import com.google.gwt.ajaxloader.client.AjaxLoader; 
import com.google.gwt.ajaxloader.client.AjaxLoader.AjaxLoaderOptions; 
import com.google.gwt.core.client.EntryPoint; 
import com.google.gwt.dom.client.Document; 
import com.google.gwt.event.dom.client.ClickEvent; 
import com.google.gwt.event.dom.client.ClickHandler; 
import com.google.gwt.user.client.ui.Button; 
import com.google.gwt.user.client.ui.RootPanel; 
import com.google.maps.gwt.client.GoogleMap; 
import com.google.maps.gwt.client.LatLng; 
import com.google.maps.gwt.client.MapOptions; 
import com.google.maps.gwt.client.MapType; 
import com.google.maps.gwt.client.MapTypeId; 

public class GwtMapTest implements EntryPoint { 

    @Override 
    public void onModuleLoad() { 
     AjaxLoaderOptions options = AjaxLoaderOptions.newInstance(); 
     options.setOtherParms("sensor=false"); 
     Runnable callback = new Runnable() { 
      public void run() { 
       createMap(); 
      } 
     }; 
     AjaxLoader.loadApi("maps", "3", callback, options); 
    } 

    public void createMap() { 

     MapOptions mapOpts = MapOptions.create(); 
     mapOpts.setZoom(4); 
     mapOpts.setCenter(LatLng.create(37.09024, -95.712891)); 
     mapOpts.setMapTypeId(MapTypeId.TERRAIN); 
     mapOpts.setStreetViewControl(false); 

     final GoogleMap map = GoogleMap.create(Document.get().getElementById("map_canvas"), mapOpts); 
     addWeatherLayer(map); 

     Button button = new Button("Gwt Refresh"); 
     button.addClickHandler(new ClickHandler(){ 

      @Override 
      public void onClick(ClickEvent event) { 
       refreshWeatherLayer(map); 
      } 
     }); 

     Button nativeButton = new Button("Native Refresh"); 
     nativeButton.addClickHandler(new ClickHandler(){ 

      @Override 
      public void onClick(ClickEvent event) { 
       nativeRefreshWeatherLayer(map); 
      } 
     }); 

     RootPanel.get().add(button); 
     RootPanel.get().add(nativeButton); 
    } 

    public native void addWeatherLayer(GoogleMap map) /*-{ 
     var imageMapType = new $wnd.google.maps.ImageMapType({ 
      getTileUrl: function(coord, zoom) { 
       return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/"+ zoom + "/" + coord.x + "/" + coord.y + ".png"; 
      }, 
      tileSize: new $wnd.google.maps.Size(256, 256), 
      opacity:.50, 
      isPng: true 
     }); 

     map.overlayMapTypes.setAt("0", imageMapType); 

    }-*/; 

    private void refreshWeatherLayer(GoogleMap map){ 
     double zoom = map.getZoom(); 
     map.setZoom(1); 
     map.setZoom(zoom); 

     MapType layer = map.getOverlayMapTypes().getAt(0); 
     map.getOverlayMapTypes().setAt(0, null); 
     map.getOverlayMapTypes().setAt(0, layer); 
    } 

    private native void nativeRefreshWeatherLayer(GoogleMap map) /*-{ 
     var zoom = map.getZoom(); 
     map.setZoom(1); 
     map.setZoom(zoom); 

     $wnd.google.maps.event.trigger(map, 'resize'); 

     var layer = map.overlayMapTypes.getAt(0); 
     map.overlayMapTypes.setAt(0, null); 
     map.overlayMapTypes.setAt(0, layer); 
    }-*/; 

} 

Należy to zrobić to samo, co na przykład czystej JavaScript. Zamiast tego, gdy klikam przycisk, mapa odświeża (widzę mrugającą warstwę pogody), , ale tak naprawdę nie przechodzi do serwera kafelków dla nowych płytek.

Jeszcze dziwniej, ten "sorta" działa w Internet Explorerze: może 1 na 3 razy kliknę przycisk, mapa faktycznie trafia do serwera kafelków. Ale w Chrome nigdy nie trafia do serwera kafelków po kliknięciu przycisku.

Aby to ustalić, patrzę na kartę sieci narzędzi przeglądarki. Spodziewałbym się, że mapa uderzy w serwer kafli za każdym razem, gdy kliknę przycisk. To jest to, co robi w czystym JavaScript, i to było to, co robił w GWT, ale czasami w ciągu ostatnich kilku miesięcy zmieniło się zachowanie GWT.

Nie sądzę, że jest to problem z buforowaniem przeglądarki. Problem polega na tym, że mapa próbuje pobrać nowe kafelki, ale robi stare, ponieważ nigdy nie próbuje pobrać nowych płytek. Klikam przycisk i nic nie dzieje się na karcie sieci narzędzi programistycznych.

  • Dlaczego widzę inne zachowanie w JavaScript vs GWT?
  • Dlaczego widzę inne zachowanie w różnych przeglądarkach?
  • Czy biblioteka GWT GoogleMaps wykonuje jakieś wewnętrzne buforowanie? Czy istnieje sposób, aby to wyłączyć?
  • Dlaczego to zachowanie najwyraźniej się zmieniło?
  • Jak mogę odświeżyć mapę GWT, przechodząc do serwera kafelków dla nowych płytek?
+0

Przetestowałem skrypt w obu przeglądarkach i wypróbowałem go na GWT. Jedną z różnic, które znalazłem, jest to, że w przeglądarkach umieszczają znacznik czasu po kafelku (/ZOOM/X/Y.png?TIME). Kod GWT najwyraźniej tego nie robi. W przeglądarce, jeśli godzina jest pominięta, IE pobiera ją z serwera, a Chrome pobiera ją z localcache. Być może zmiana dotyczyła serwera kafelkowego (lub konkretnego serwera proxy), który buforuje kafelek. Czy możesz spróbować zaktualizować żądanie w kodzie GWT z parametrem?? TIME? – fhofmann

+0

@fhofmann To zadziałało, co jest dla mnie zaskakujące. Zwykle dodaje się część '? Time', aby uniknąć pamięci podręcznej przeglądarki, co w tym przypadku nie stanowiło problemu, ponieważ nigdy nie trafiła na serwer, a zatem nawet nie sprawdzała pamięci podręcznej przeglądarki. Wygląda więc na to, że musi być jakieś wewnętrzne buforowanie, ale tylko w wersji GWT, która nie ma dla mnie żadnego sensu. Czy możesz wyjaśnić ** dlaczego ** wersje GWT i JS są inne lub dlaczego funkcja '? Time' działa w GWT? Jeśli chcesz dodać to jako odpowiedź, zdecydowanie to doceniam. –

+0

Właściwie nigdy wcześniej nie używałem GWT. Ale teraz jestem ciekawa, a ja spróbuję znaleźć, jak to działa i gdzie może to być buforowanie. – fhofmann

Odpowiedz

1

To nie jest ostateczna odpowiedź. Ale zawiera istotne informacje.

Aby zarządzać połączeniami http GWT ma zestaw klas działających jak przeglądarka i jest tam, gdzie uważam, że jest problem.

Jeśli ten sam kod pracował wcześniej, jest możliwe, że serwer kaflowy zawiera ostatnio nagłówek Cache (Cache-Control: max-age = 300). I z jakiegoś powodu kod GWT nie zarządza poprawnie tym nagłówkiem.

Jeśli mam rację, sposobem na rozwiązanie problemu jest dołączenie parametru z bieżącym czasem w wywołaniu GWT (np. Wersja przeglądarki kodu).

public native void addWeatherLayer(GoogleMap map) /*-{ 
    var imageMapType = new $wnd.google.maps.ImageMapType({ 
     getTileUrl: function(coord, zoom) { 
      return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/"+ zoom + "/" + coord.x + "/" + coord.y + ".png?" + new Date().getTime(); 
     }, 
     tileSize: new $wnd.google.maps.Size(256, 256), 
     opacity:.50, 
     isPng: true 
    }); 

    map.overlayMapTypes.setAt("0", imageMapType); 

}-*/; 
+0

Masz odpowiednie rozwiązanie, ale nie sądzę, że problem dotyczy GWT. To moja wina, ponieważ nie zdawałem sobie sprawy, że mam część "? Time" w mojej wersji JavaScript. Jeśli to zrobię, działa jak wersja GWT. Jeśli dodaję go do wersji GWT, to działa idealnie. ** Problem tkwi w podstawowej bibliotece JavaScript, a nie w GWT. ** Najwyraźniej Google Maps robi pewne wewnętrzne buforowanie, co oznacza również, że ** zmiana kontroli pamięci podręcznej serwera kafelkowego nic nie da. ** I ' Jestem pewien, że to nowe zachowanie, ale nie mogę powiedzieć, ponieważ kod jest zaciemniony. –

+0

Powiedziawszy to, wskazałeś na część '? Time' w moim JavaScript, więc zasługujesz na nagrodę. To była ogromna pomoc. Nie sądzę jednak, abyśmy znaleźli przyczynę problemu, ponieważ jest on wbudowany w interfejs API Map Google, który jest zaciemniany. Uwielbiam jakieś oficjalne słowo, czy coś zmieniło się tylko dla mojego własnego zdrowia psychicznego, ale na razie to działa, więc jestem szczęśliwy. –

+0

Zrobiłem kolejny test. Tym razem skompilowałem kod GWT i wskazałem go na fałszywy serwer kaflowy (lokalny serwlet przywracający bieżący czas na obrazku). Moim celem było udowodnienie, że nagłówek pamięci podręcznej jest problemem i zobacz, gdzie GWT pobiera i zarządza obrazem. Niestety otrzymuję błąd skryptu i nie widzę, aby aplikacja działała. – fhofmann

Powiązane problemy