2017-02-17 9 views
0

Как можно отправить функцию (копию) из моей основной темы моему работнику?Post function to webworker

Всякий раз, когда я пытаюсь: worker.postMessage({data, func: (data) => data), firefox дает мне сообщение об ошибке: DataCloneError: Объект не может быть клонирован.

Что касается Chrome, то сообщение отличается, но ошибка все еще возникает: Uncaught DOMException: Не удалось выполнить 'postMessage' в 'Worker': объект не может быть клонирован.

ответ

1

Не тестировалось это еще, но мне кажется, что из спецификации, только объекты, которые могут быть посылают на работника являются «Переводные» объекты: https://developer.mozilla.org/en-US/docs/Web/API/Transferable

Я нашел несколько примеров, в первом процесс не детально, но я предполагаю, что он использует вид или URL-кодирование, для объекта он может быть преобразован в JSON, как во втором примере.

How to pass functions to JavaScript Web Worker

Passing objects to a web worker

я должен это делать в течение нескольких дней, я могу держать в курсе того, что я, что будет испытано ..

+0

Чтобы иметь возможность размещать какую-либо функцию, анонимным включено, мне нужно позвонить [ToString] (https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Function/toString), а затем [eval] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#eval_as_a_string_defining_function_requires_ (_and_) _as_prefix_and_suffix) it изнутри рабочего. – Wanderson

0

Да, это возможно, Я сделал это, и лучше, чем я могу создавать веб-работников без js-файлов, просто используя файлы Blob, созданные с помощью javascript-кода.

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; 
 
    } 
 
}