简体   繁体   中英

Post function to webworker

How is it possible to send a (copy of) function from my main thread to my worker?

Whenever I try: worker.postMessage({data, func: (data) => data) , firefox gives me an error message: DataCloneError: The object could not be cloned.

As for Chrome, the message differ, but the error still occur: Uncaught DOMException: Failed to execute 'postMessage' on 'Worker': An object could not be cloned.

Yes, it is possible, I did that , and better than that I can create web workers without js files, just using Blob files generated with javascript code.

 setInterval(()=>{console.log("non bloked " + Math.random())}, 900) console.log("starting blocking code in Worker") console.time("blocked") genericWorker(window, ["blockCpu", function (block){ block(10000) //This blockCpu function is defined below return `\\n\\nbla ${123123*2312} bla \\n` //This is catched in the resolved promise }]).then(function (result){ console.timeEnd("blocked") console.log("End of blocking code", result) }) .catch(function(error) { console.log(error) }) /* A Web Worker that does not use a File, it create that from a Blob @cb_context, The context where the callback functions arguments are, ex: window @cb, ["fn_name1", "fn_name2", function (fn1, fn2) {}] The callback will be executed, and you can pass other functions to that cb */ function genericWorker(cb_context, cb) { return new Promise(function (resolve, reject) { if (!cb || !Array.isArray(cb)) return reject("Invalid data") var callback = cb.pop() var functions = cb if (typeof callback != "function" || functions.some((fn)=>{return typeof cb_context[fn] != "function"})) return reject(`The callback or some of the parameters: (${functions.toString()}) are not functions`) if (functions.length>0 && !cb_context) return reject("context is undefined") callback = fn_string(callback) //Callback to be executed functions = functions.map((fn_name)=> { return fn_string( cb_context[fn_name] ) }) var worker_file = window.URL.createObjectURL( new Blob(["self.addEventListener('message', function(e) { var bb = {}; var args = []; for (fn of e.data.functions) { bb[fn.name] = new Function(fn.args, fn.body); args.push(fn.name)}; var callback = new Function( e.data.callback.args, e.data.callback.body); args = args.map(function(fn_name) { return bb[fn_name] }); var result = callback.apply(null, args) ;self.postMessage( result );}, false)"]) ) var worker = new Worker(worker_file) worker.postMessage({ callback: callback, functions: functions }) worker.addEventListener('error', function(error){ return reject(error.message) }) worker.addEventListener('message', function(e) { resolve(e.data), worker.terminate() }, false) //From function to string, with its name, arguments and its body function fn_string (fn) { var name = fn.name, fn = fn.toString() return { name: name, args: fn.substring(fn.indexOf("(") + 1, fn.indexOf(")")), body: fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}")) } } }) } //random blocking function function blockCpu(ms) { var now = new Date().getTime(); var result = 0 while(true) { result += Math.random() * Math.random(); if (new Date().getTime() > now +ms) return; } } 

Not tested this yet, but it seems that from the spec, only objects that can be send to a Worker are "Transferable" objects: https://developer.mozilla.org/en-US/docs/Web/API/Transferable

I found some examples, in the first one the process is not detailled, but i'm guessing he uses a kind or URL encode, for an object, it can be converted to JSON like in the second example.

How to pass functions to JavaScript Web Worker

Passing objects to a web worker

I have to do this too in a couple of days, i can keep updated with what i have that will be tested..

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