4 votos

Reintento de carga fallida de baldosas TileWMS en OpenLayers

Tengo un mapa en OpenLayers con fuente TileWMS que no es muy fiable. En casi todas las cargas de página completa hay algunos azulejos que no se cargan con el estado 503 - Service Unavailable . Cuando intento cargar el azulejo fallido un poco más tarde 'manualmente', se carga sin problemas. Eso me llevó a la idea de volver a cargar el azulejo fallido si el primer intento no tiene éxito.

No pude encontrar ninguna forma "oficial" de OpenLayers de hacer eso, así que traté de lograrlo usando tileLoadFunction donde inicio la recarga del mosaico con 2 segundos de retraso y antes de la recarga compruebo si el mosaico ya se ha cargado correctamente. La recarga se activa asignando primero una fuente de imagen ficticia para el mosaico y luego la original. El éxito de la carga de la baldosa se comprueba por enganche en tileloadend y configuración de la bandera personalizada evt.tile._loaded = true .

He aquí el código correspondiente:

proj4.defs('EPSG:3912',
           '+proj=tmerc +lat_0=0 +lon_0=15 +k=0.9999 +x_0=500000 +y_0=-5000000 +ellps=bessel +towgs84=682,-203,480,0,0,0,0 +units=m +no_defs');
var proj3912 = ol.proj.get('EPSG:3912');
proj3912.setExtent([374371.84, 30513.32, 624119.18, 195517.48]);

var tileGridResolutions = [1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5];

var dofLayer = new ol.layer.Tile({
  source: new ol.source.TileWMS({
    url: 'https://prostor4.gov.si/ows2-m-pub/wms',
    attributions: ['<a href="http://www.gu.gov.si/">GURS</a>'],
    params: {
      'LAYERS': 'SI.GURS.ZPDZ:DOF050_D48',
      'FORMAT': 'image/png',
      'VERSION': '1.3.0'
    },
    tileGrid: new ol.tilegrid.TileGrid({
      extent: proj3912.getExtent(),
      resolutions: tileGridResolutions,
      tileSize: 256
    }),
    tileLoadFunction: tileLoadFunction,
    projection: proj3912
  }),
  title: 'Ortofoto',
  type: 'base'
});

function tileLoadFunction(imageTile, src) {
  imageTile.getImage().src = src;
  if (typeof imageTile._retry == 'undefined') {
    imageTile._retry = 0;
    imageTile._loaded = false;
  }
  if (imageTile._retry < 3) {
    imageTile._retry++;
    setTimeout(function() {
      if (!imageTile._loaded) {
        imageTile.getImage().src = 'img/empty.png';
        tileLoadFunction(imageTile, src);
      }
    }, 2000);
  }
}

dofLayer.getSource().on('tileloadend', function(evt) {
  evt.tile._loaded = true;
});

Por desgracia, este método sólo funciona en el venerable IE11, pero no en Firefox y Chrome. No hay ningún error, sólo parece que la imagen no se transfiere desde el elemento de imagen al lienzo. Dado que trabajo en ES5 JS, no puedo depurar los componentes internos de OpenLayers para ver dónde está el problema.

¿Hay alguna manera de hacer que el método anterior funciona en Firefox y Chrome o algún otro enfoque para tratar de recarga falló TileWMS ¿Teja?

2voto

Bob Johnson Puntos 26

Usted obtendría más control de carga a través de xhr como en https://openlayers.org/en/main/apidoc/module-ol_Tile.html#~CargarFunción y programando un reintento desde el manejador de error/tiempo de espera del xhr.

No debería ser necesario ningún tratamiento de errores una vez que se tiene una url de objeto, pero para evitar fugas de memoria

tile.getImage().src = URL.createObjectURL(data);

debe sustituirse por

var url = URL.createObjectURL(data);
tile.getImage().onload = function(){
  URL.revokeObjectURL(url);
}
tile.getImage().src = url;

ACTUALIZACIÓN

Este código de ejemplo utilizando una fuente muy propensa a errores está dando algunos éxitos en un segundo intento después de 5 segundos, mientras que algunos azulejos siguen fallando.

  var map = new ol.Map({
    target: 'map',
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM({
          url: 'https://{a-c}.tile.opentopomap.org/{z}/{x}/{y}.png',
          maxZoom: 17,
          tileLoadFunction: function (tile, src) {
            function attemptLoad(attempt) {
              var xhr = new XMLHttpRequest();
              xhr.responseType = 'blob';
              xhr.addEventListener('load', function (evt) {
                var data = this.response;
                if (data !== undefined) {
                  var url = URL.createObjectURL(data);
                  if (attempt > 1) {
                    console.log('success at 2nd attempt ' + src);
                  }
                  tile.getImage().addEventListener('load', function () {
                    URL.revokeObjectURL(url);
                  });
                  tile.getImage().src = url;
                } else {
                  console.log('no data ' + src);
                  tile.setState(3);
                }
              });
              xhr.addEventListener('error', function () {
                if (attempt > 1) {
                  console.log('fail at 2nd attempt ' + src);
                  tile.setState(3);
                } else {
                  setTimeout(function () {
                    console.log('retry ' + src);
                    attemptLoad(attempt + 1);
                  }, 5000);
                }
              });
              xhr.open('GET', src);
              xhr.send();
            }
            attemptLoad(1);
          }
        })
      })
    ],
    view: new ol.View({
      center: [0, 0],
      zoom: 2
    })
  });

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X