I want to use dracoLoader of threeJS in multi-threads, then I selected Webworker and IndexedDB. I have gotten the correct Geometry in webworker, however, when I pass data to main thread using IndexedDB, the geometry will be changed to a normal JS object instead of a ThreeJS Geometry. The geometry lost its functions and some information.
webworker.js
self.saveDrcToIndexedDB = function (drcfinal) {
var db;
var request = indexedDB.open("drcDB");
drcfinal.indexName = self.randomStr();
request.onupgradeneeded = function(event) {
console.log('successfully upgraded db');
db = event.target.result;
var objectStore = db.createObjectStore("drcfinal", { keyPath: "indexName"});
};
request.onsuccess = function(event) {
console.log('successfully opened db');
db = event.target.result;
var transaction = db.transaction(["drcfinal"], "readwrite");
var objectStore = transaction.objectStore("drcfinal");
objectStore.add(drcfinal).onsuccess = function(event) {
self.postMessage(drcfinal.indexName);
};
}
}
main.js
var worker = new Worker('webworker.js');
worker.addEventListener('message', function(e) {
indexedDB.open("drcDB").onsuccess = function(event) {
let db = event.target.result;
let objectStore = db.transaction(["drcfinal"]).objectStore("drcfinal");
objectStore.get(e.data).onsuccess = function(event) {
console.log(event.target.result);
};
}
}, false);
worker.postMessage(somedata);
Can I transfer a correct geometry to main thread? Or using other tools instead of IndexedDB? Or using other multi-threading tools instead of webworker?
A mechanism called Structured Cloning is used when storing data in IndexedDB. Same applies to sending messages to and from WebWorkers via postMessage. It is not possible with this approach to duplicate functions. Thus you cannot transfer complete objects including their methods. Simply put, it is a better JSON.stringify/parse approach since Structured Cloning can e.g. handle cyclic dependencies.
AFAIK all web-browser available multi threading mechanisms such as WebWorker, SharedWorker and ServiceWorker use this actor based message sending approach.
However, you could use a Transferable object to transfer data from a WebWorker to the main thread using Worker.postMessage. This way, you could send THREE.Geometry's vertex array as a Transferable. E.g. when using a THREE.BufferGeometry within WebWorker.
const myVertexData = bufferGeometry.getAttribute('position').array.buffer;
self.postMessage({myVertices: myVertexData}, [myVertexData]);
This is quite fast since the data is not copied but only its ownership is changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With