workers usar threads support script examples end como javascript web-worker

javascript - usar - web workers jquery



Cómo pasar funciones a JavaScript Web Worker (3)

Para aquellos que buscan una respuesta más genérica: aquí hay un plugin, que le permite ejecutar cualquier función de su código javascript en un hilo.

http://www.eslinstructor.net/vkthread/

Considérelo como "externalización de funciones". Usted pasa cualquier función al complemento como argumento y obtiene un resultado en la devolución de llamada. También puede "externalizar" los métodos de los objetos, funcionar con dependencias, funciones anónimas y lambda.

Disfrutar.

--Vadim

Me gustaría pasar una función (o funciones) a través de un postMessage() a un trabajador web, porque no puedo referirme a archivos normales.

Para expulsar al trabajador web, estoy pasando una URL de objeto (creada a partir de un Blob) al constructor del Worker . Luego estoy pasando un mensaje, pero hasta ahora no he tenido suerte al poner una función en el mensaje.

El mensaje (JSON) no puede contener funciones directamente (como se estipula here ), y aunque teóricamente se permiten importScripts, no he tenido ningún éxito en usarlo hasta ahora en Chrome o Firefox.

El cuerpo del archivo html:

<div id="divText">1234</div> <script> var greeter = function greet(name) { return "hello " + name; }; function webWorkerWorker() { self.postMessage("started1"); self.onmessage = function(event) { importScripts(event.data.content); self.postMessage("importScripts success"); var result = greeter("john"); self.postMessage(result); }; } var functionBody = mylib.extractFunctionBody(webWorkerWorker); var functionBlob = mylib.createBlob([functionBody]); var functionUrl = mylib.createObjectURL(functionBlob); var functionBody2 = mylib.extractFunctionBody(greeter); var functionBlob2 = mylib.createBlob([greeter]); var functionUrl2 = mylib.createObjectURL(functionBlob2); var worker = new Worker(functionUrl); worker.onmessage = function(event) { document.getElementById("divText").innerHTML = event.data; } worker.postMessage({ type: "init", content: functionUrl2 }); </script>

Actualmente da como resultado la configuración del valor de divText en "importScripts success".

¿Estoy haciendo algo mal? ¿Hay otra forma en que las funciones se pueden pasar a los trabajadores web? ¿O acaso no es posible?


Resulta que este método funciona bien, solo había un error en mi trabajador:

var result = greeter("john");

debiera ser

var result = greet("john");

lo que tiene sentido: estoy pasando la variable de bienvenida al trabajador, pero no hay razón para que sepa el nombre de la variable del objeto que estoy pasando.


Sí, claro que es posible, lo implementé.

Esta es una promesa que ejecutará el trabajador genérico.

/* @data.context, The context where the callback functions arguments are, ex: window @data.callback, ["fn_name1", "fn_name2", function (fn1, fn2) {}] The callback will be executed, and you can pass other functions to that cb @worker_url string url of generic web worker */ function genericWorker(worker_url, data) { return new Promise(function (resolve, reject) { if (!data.callback || !Array.isArray(data.callback)) return reject("Invalid data") var callback = data.callback.pop() var functions = data.callback var context = data.context if (!worker_url) return reject("Worker_url is undefined") if (!callback) return reject("A callback was expected") if (functions.length>0 && !context) return reject("context is undefined") callback = fn_string(callback) //Callback to be executed functions = functions.map((fn_name)=> { return fn_string( context[fn_name] ) }) var worker = new Worker(worker_url) 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("}")) } } }) }

El archivo de trabajo genérico worker_for_anything.js

self.addEventListener(''message'', function(e) { var worker_functions = {} //Functions used by callback var args = [] //Arguments of the callback for (fn of e.data.functions) { worker_functions[fn.name] = new Function(fn.args, fn.body) args.push(fn.name) } var callback = new Function( e.data.callback.args, e.data.callback.body) //Callback passed and ready to be executed args = args.map((fn_name) => { return worker_functions[fn_name] }) //FUnctions loaded as arguments var result = callback.apply(null, args) //executing callback with function arguments self.postMessage( result ) }, false)

Usándolo :)

var data = { context: window, //the context of the functions passed, ex: window for blockCpu callback: ["blockCpu", function (bla) { bla(7000) //blocking for 7000 ms return "bla" //This return is catched in the promise }] } genericWorker("/worker_for_anything.js", data) .then(function (result){ console.log("result", result) }).catch((error)=> { console.log(error) }) //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; } }