Question

I'm working on a webApp which shows clustered lightning occurrences on a map (so a huge cluster is like a thunderstorm formation).

To avoid 'freezing' the user interface, i'm using a Javascript Worker to perform the clustering. The problem happens when the algorithm finishes, because it returns a custom object which 'loses' some properties after i send it to the main page:

//inside Worker.js
var cluster = new DBSCAN(e.data.params).run();
self.postMessage({"cluster": cluster});

The cluster object is basically an array of GeoPoint objects, so:

cluster[0]

is a GeoPoint object like this

function GeoPoint(lat, lng){
    this.lat_ = lat;
    this.lng_ = lng;
}
GeoPoint.prototype.lat = function(){ return this.lat_;}
GeoPoint.prototype.lng = function(){ return this.lng_;}

When i send this object with self.postMessage i lose the lat() and lng() functions, which i need to draw the polygons. The lat_ and lng_ properties are intact though.

What can i do to overcome this? Right now i'm simply looping over the results and reconstructing the GeoPoint objects, it works but seems very bad.

Thanks for any advice!

EDIT: I need those functions because the drawing code will perform a sorting on the lat lon points, before it can calculate the convex hull.

Était-ce utile?

La solution

What can i do to overcome this?

Nothing - the cloning algorithm used by postMessage does not transport prototypes and functions. Reconstructing them on the other side is necessary.

Right now i'm simply looping over the results and reconstructing the GeoPoint objects, it works but seems very bad.

No, that's what needs to be done:

var newCluster = messageData.cluster.map(function(likeapoint) {
    var point = new GeoPoint();
    for (p in likeapoint)        // maybe a static list of copied property names
        point[p] = likeapoint[p];// is faster, but not as flexible
    return point;
})

// since all properties are settable as arguments in this specific case:
var newCluster = messageData.cluster.map(function(likeapoint) {
    return new GeoPoint(likeapoint.lat_, likeapoint.long_);
})

Autres conseils

According to the documentation, postMessage uses the structured clone algorithm. Functions and prototypes are not transferred :

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/The_structured_clone_algorithm?redirectlocale=en-US&redirectslug=Web%2FGuide%2FDOM%2FThe_structured_clone_algorithm

What you can try after receiving your data is change the prototype of the received objects :

worker.onmessage = function(event) {
    var data = event.data;
    data.forEach(function(p) {
        p.__proto__ = GeoPoint.prototype; // That seems to work, but I'm really not sure if this is standard and compatible with all browsers !
    });
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top