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? Commented Jul 9, 2015 at 16:01
  • @JonatasWalker, yes it exists.
    – johjoh
    Commented Jul 14, 2015 at 17:57

3 Answers 3

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
    Commented Apr 4, 2017 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
    Commented Jul 8, 2015 at 18:15
  • the link is not working anymore but the solution does, even in OL 6.5, thank you!
    – Radek
    Commented Apr 10, 2021 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
    Commented Apr 4, 2017 at 22:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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