简体   繁体   中英

Pass object by reference from/to webworker

Is it possible passing an object from/to webWorker from/to main thread by reference? I have read here information about transferable objects.

Chrome 13 introduced sending ArrayBuffers to/from a Web Worker using an algorithm called structured cloning. This allowed the postMessage() API to accept messages that were not just strings, but complex types like File, Blob, ArrayBuffer, and JSON objects. Structured cloning is also supported in later versions of Firefox.

I just want to pass information, not object with methods. Just something like this (but with a lot of information, a few MB, so that main thread does not have to receive a copy of the object):

var test = {
    some: "data"
}

There Is An Array 2nd Argument To postMessage

Actually yes, it is possible in, (surprise, Surprise!) Chrome 17+ and Firefox 18+ for certain objects ( see here ).

// Create a 32MB "file" and fill it.
var uInt8Array = new Uint8Array(1024 * 1024 * 32); // 32MB
for (var i = 0; i < uInt8Array.length; ++i) {
  uInt8Array[i] = i;
}
worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);

You can also apply this to strings by converting the string to and from an array buffer using FastestSmallestTextEncoderDecoder as shown below.

//inside the worker
var encoderInst = new TextEncoder;
function post_string(the_string){
    var my_array_buffer = encoderInst.encode(the_string).buffer;
    postMessage( my_array_buffer, [my_array_buffer] );
}

Then, to read the arraybuffer as a string:

// var workerInstance = new Worker("/path/to/file.js");
var decoderInst = new TextDecoder;
workerInstance.onmessage = function decode_buffer(evt){
    var buffer = evt.data;
    var str = decoderInst.decode(buffer);
    console.log("From worker: " + str);
    return str;
}

Here is a small interactive example of using a Worker to increment each letter of a string.

 var incrementWorker = new Worker("data:text/javascript;base64,"+btoa(function(){ // inside the worker importScripts("https://dl.dropboxusercontent.com/s/r55397ld512etib/Encode" + "rDecoderTogether.min.js?dl=0"); const decoderInst = new TextDecoder; self.onmessage = function(evt){ const u8Array = new Uint8Array(evt.data); for (var i=0, len=u8Array.length|0; i<len; i=i+1|0) { ++u8Array[i]; } postMessage(decoderInst.decode(u8Array)); }; } .toString().slice("function(){".length, -"}".length))); const inputElement = document.getElementById("input"); const encoderInst = new TextEncoder; (inputElement.oninput = function() { const buffer = encoderInst.encode(inputElement.value).buffer; incrementWorker.postMessage(buffer, [buffer]); // pass happens HERE })(); incrementWorker.onmessage = function(evt){ document.getElementById("output").value = evt.data; }; 
 <script src="https://dl.dropboxusercontent.com/s/r55397ld512etib/EncoderDecoderTogether.min.js?dl=0" type="text/javascript"></script> Before: <input id="input" type="text" value="abc123 foobar" /><br /> After:&nbsp;&nbsp; <input id="output" type="text" readonly="" /> 


Sources: Google Developers and MDN

It is not possible. You have to send the object, update it in the worker and then return the updated version to the main thread.

If you want to pass an object just with information, you only need to pass your object as a string

myWorker.postMessage(JSON.stringify(myObject)); 

parse the object inside your worker

JSON.parse(myObject)

and finally return your updated object to the main thread. Take a look also to ParallelJs that is library to work easier with web-workers

Once you have some data in an object (this: {bla:666, color:"red"} ) you will have to copy it and there is no way to avoid it. The reason is, that you don't have control over the memory object is stored in, so you can't transfer it. The only memory that can be transferred is memory allocated for transferable objects - typed arrays.

Therefore if you need some data transferred, you must think in advance and use the transferable interface. Also keep in mind that even when object is copied, the transfer speed is very fast.

I wrote a library that converts object to binary data (therefore transferable), but it isn't faster than native transfer, it's way slower actually. The only advantage is that it allows me to transfer unsupported data types (eg. Function ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM