1

I am pretty new to this field and struggling to find out whether my idea is worth pursuing further.

The problem I am facing is that I have to load a couple of large GeoJSON layers into my OpenLayers map. This takes around 3 seconds on my machine and during this time the UI freezes. The loading time as such is not an issue, but the freezing is.

Now I am wondering whether it would be possible/useful to move the layer creation to a web worker in order the free the main thread. I have seen some basic examples of this happening, i.e.: http://dev.openlayers.org/sandbox/camptocamp/canvas/openlayers/examples/geojson-webworker.html. But this is a very old version of OpenLayers, and possibly some sort of experimental build

I have read quite a lot of threads claiming that this would not be a solution as a web worker can not access the dom and this is where the delay happens.

Could someone advise me on this?


I just realised there was no need to pass the ol object to the worker via the main thread. Instead I could do self.importScripts("/node_modules/openlayers/dist/ol.js"); in the worker.

However this throws an error Uncaught ReferenceError: document is not defined because ol depends on the document object to be present.

So unless there is some way to import only a subset of OpenLayers, which doesn't rely on the document object, and still enables me to create layers in a worker, I think I am stumped.

So my questions now are:

  1. Is there any way to create the layers aSync with OpenLayers?
  2. Is there another mapping library around which makes this possible?
  3. Is there a better way to work with a huge offline map? I.e. work with a giant set of tiles as opposed to one large geoJSON?

I am keeping the section below for historical references ;-)

Sorry for my late reply, I've had to work on a different application for a while and have just returned now.

In response to the remark of @pavlos: Loading the JSON is only a small part of the problem. The main lag is in the actual processing of the layers, especially one of them which needs a style dynamically applied to it for each LineString feature section.

I have experimented a little with a web worker with poor results. The problem is the inaccessibility of the OpenLayers library in the worker, and passing complex objects from main thread to web worker in general. I can share some code snippets below though, perhaps someone has any ideas....

My main idea was to create a map on the main thread and the layers in a web worker, and add them to the map once they are done.

Main script section:

var mapConf, worker;

// Get map config
mapConf        = getMapConf();
// Create OpenLayers Map
$scope.map     = new ol.Map(mapConf);

// Create a web worker to create layers off the main thread
worker = new Worker('/app/shared/components/ais/mapWorker.js');
// Worker init
createMapLayersInWorker();

// This event listener would receive the layers from the worker
// once I figure out how to create them on the worker
worker.onmessage = function (event) {
    console.log(event.data);
    // Get the map layers from the event data
    // Add to map
    // Call stopMapWorker to stop worker
};

// Fires up the worker
function createMapLayersInWorker () {
    // The worker needs to have acces to OpenLayers so I need to pass it somehow
    // However, it can't be transferred as a transferable object it has to be stringified and copied :-(
    worker.postMessage({cmd: 'createMapLayers', ol: JSON.stringify(ol)});
}

// Helper to close worker when done
function stopMapWorker () {
    worker.postMessage({cmd: 'stop'});
}

// Create configuration object for map
function getMapConf () {
    var mapConf = {
        // Some settings needed by my app
        ...
    };
    return mapConf;
}

Worker:

// Message handler
self.onmessage = function (e) {
    switch (e.data.cmd) {
        case 'createMapLayers':
            // Start creating the layers, pass the ol object
            createMapLayers(JSON.parse(e.data.ol));
            break;
        case 'stop':
            self.close();
            break;
        default:
            console.error('Received unknown worker message', e);
    }
};

function createMapLayers (ol) {
    var mapLayerStyles, mapLayers;
    // Add ol to worker
    self.ol = ol;
    // NOTE: ol object has the properties I would like to see, such as ol.style,
    // but on further inspection they are empty
    console.log(ol);
    mapLayerStyles = getMapLayerStyles();
    mapLayers      = getMapLayers(mapLayerStyles);
    console.log('created map layers', mapLayers);
}

function getMapLayerStyles () {
    // Code removed, but the styles were created correctly on the main thread
    ...
}

function getMapLayers (mapLayerStyles) {
    // Code removed, but the layers were created correctly on the main thread
    ...
}

Can someone let me know if it would somehow be possible to work in a way similar to this with OpenLayers, or any other mapping library? It seems like a sensible approach....

closed as too broad by PolyGeo Feb 18 '16 at 21:16

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • perhaps you can instantiate the layer and point to the json data in a webworker. after thats done, add the layer to the map on the main thread. Not sure if this would work. leaflet for example, has a plugin to load json async. Leaflet is very different from OL, but perhaps a similar approach would work: lyzidiamond.com/posts/… – George Silva Feb 3 '16 at 15:20
  • Freezing has to do with synchronous request. So the solution is to load the json asynchronous. Can you provide us the code you use to load the geojson file, so we can guide you to do it asynchronous. – pavlos Feb 4 '16 at 10:44
  • This question has become discussion-like encompassing multiple questions, and as a result more difficult to answer. I recommend you revise it heavily to make clear what your current single focused question is. – PolyGeo Feb 18 '16 at 21:18