8

ol.source.getState() doesn't seem to be reliable. When I call it on a vector source it returns ready, but the features are not available yet. Code looks like this:

var vectorSource = new ol.source.Vector({
  url: 'world.topo.json',
  format: new ol.format.TopoJSON()
});

// ... init map with vectorSource

console.log(vectorSource.getState()); // returns "ready"
console.log(vectorSource.getFeatureById("US")); // returns null

Any other way to see if a vector source is ready?

2
  • Did you check if this feature ID exists? Jul 9 '15 at 16:01
  • @JonatasWalker, yes it exists.
    – johjoh
    Jul 14 '15 at 17:57
8

You can provide your own loader function and set some custom listeners, as it follows:

var source = new ol.source.Vector({
    loader: function(){
        var url = '....../data/json/world-110m.json';
        var format = new ol.format.TopoJSON();
        var source = this;

        //dispatch your custom event
        this.set('loadstart', Math.random());

        getJson(url, '', function(response){

            if(Object.keys(response).length > 0){
                var features = format.readFeatures(response, {
                    featureProjection: 'EPSG:3857'
                });
                source.addFeatures(features);
                //dispatch your custom event
                source.set('loadend', Math.random());
            }
        });
    }
});

Set some custom listeners:

//custom source listener
source.set('loadstart', '');
source.set('loadend', '');

source.on('change:loadstart', function(evt){
    console.info('loadstart');
});
source.on('change:loadend', function(evt){
    console.info('loadend');
});

And a xhr function:

var getJson = function(url, data, callback) {

    // Must encode data
    if(data && typeof(data) === 'object') {
        var y = '', e = encodeURIComponent;
        for (x in data) {
            y += '&' + e(x) + '=' + e(data[x]);
        }
        data = y.slice(1);
        url += (/\?/.test(url) ? '&' : '?') + data;
    }

    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", url, true);
    xmlHttp.setRequestHeader('Accept', 'application/json, text/javascript');
    xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState != 4){
            return;
        }
        if (xmlHttp.status != 200 && xmlHttp.status != 304){
            callback('');
            return;
        }
        callback(JSON.parse(xmlHttp.response));
    };
    xmlHttp.send(null);
};

Working demo.

1
  • This works well! Sorry for late approval. Two years ago I didn't really understand it and found my own solution – which was not reliable as it turned out now.
    – johjoh
    Apr 4 '17 at 22:47
5

You can attach a listener to your vectorSource http://openlayers.org/en/v3.7.0/apidoc/ol.source.Vector.html#once

e.g.

vectorSource.once('change',function(e){
    if (vectorSource.getState() === 'ready') {
        vectorSource.getFeatureById("US");
    }
});
2
  • Yes, that's what I already do, but the event won't fire, if the source was already loaded before. So I wanted to check if the source is ready. If so work on it immediatly – if not, bind it to the change event.
    – johjoh
    Jul 8 '15 at 18:15
  • the link is not working anymore but the solution does, even in OL 6.5, thank you!
    – Radek
    Apr 10 '21 at 9:07
0

I ended up with the following function, to execute code when the vector source is ready:

doWhenVectorSourceReady : function(callback) {
  var map = this;

  if (map.vectorSource.getFeatureById("US")) { // Is this a relieable test?
    callback();
  } else {
    var listener = map.vectorSource.on('change', function(e) {
      if (map.vectorSource.getState() == 'ready') {
        ol.Observable.unByKey(listener);
        callback();
      }
    });
  }
}

I'm not sure if testing for a single feature is reliable, as it might be, that not all features get available at the same time.

1
  • This is not reliable, as it turned out now. Checking for one feature, doesn't tell if the others are there. See the accepted answer. It works well for me.
    – johjoh
    Apr 4 '17 at 22:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.