javascript - los - Pasar objetos a un trabajador web
title html (7)
Algunos tipos de objetos, como ArrayBuffer e ImageBitmap, que tienen el implemento de interfaz Transferable y pueden transferirse sin copiar el Objeto.
Eso es muy útil en el contexto de Canvas + Web worker porque puede guardar el tiempo de copia de los datos entre los subprocesos.
Estoy tratando de pasar un objeto a un trabajador web a través de la función postMessage.
Este objeto es un cuadrado que tiene un par de funciones para dibujarse en un lienzo y algunas otras cosas. El trabajador web debe devolver una matriz de estos objetos.
El problema es que cuando llamo a la función postMessage con este objeto, aparece un error:
Uncaught Error: DATA_CLONE_ERR: DOM Exception 25
Me sale esto enviando el objeto al trabajador y al revés.
Creo que el error se debe a que javascript debe serializar el objeto, pero no puede hacerlo porque el objeto tiene funciones integradas.
¿Alguna vez alguien ha tenido un problema similar? ¿Conoces algún workarround a esto?
Gracias por adelantado.
Como sospechaste, los objetos con funciones no se pueden publicar. Lo mismo ocurre con los objetos con referencias recursivas, pero esto ha cambiado en algunos navegadores últimamente. En lugar de arriesgarse a realizar una serialización redundante manual y costosa para cada publicación, puede realizar una prueba al comienzo de su script para determinar qué funciones usar para enviar / recibir datos.
He tenido el mismo problema y lo resolví moviendo casi todo el código al trabajador y simplemente manteniendo un renderizador (envolviendo el renderizador de contexto 2d) en el hilo principal. En el trabajador, serializo las diferentes llamadas de sorteo destinadas al lienzo en números justos en una matriz (escrita). Esta matriz se publica en el hilo principal.
Entonces, por ejemplo, cuando quiero dibujar una imagen, invoco el método drawImage()
en mi instancia de renderizador de trabajador en el trabajador. La llamada se traduce en algo así como [13,1,50,40]
que corresponde al método de dibujo enum, la identificación única de la imagen y sus coordenadas xy. Varias llamadas se almacenan en búfer y se ponen en la misma matriz. Al final del ciclo de actualización, la matriz se publica en el hilo principal. La instancia del procesador principal que recibe analiza la matriz y realiza las llamadas de dibujo apropiadas.
Cuando le pasa datos a un trabajador web, se realiza una copia de los datos con el algoritmo de clonación estructurada . Se especifica en HTML5 (ver § 2.9: Transferencia segura de datos estructurados ).
MDN tiene una visión general de los tipos soportados . Como las funciones no son compatibles, intentar clonar objetos que contengan funciones generará una excepción DATA_CLONE_ERR
.
¿Qué hacer si tienes un objeto con funciones?
Si las funciones no son relevantes, intente crear un nuevo objeto que contenga solo los datos que desea transferir. Mientras use solo tipos compatibles, el envío debería funcionar. El uso de
JSON.stringify
yJSON.parse
también se puede usar como una solución alternativa, ya que la función de ignorar funciones destringify
.Si las funciones son relevantes, no hay forma portátil. Hay intentos de usar una combinación de
toString
yeval
(por ejemplo, utilizado por la biblioteca jsonfs ), pero esto no funcionará en todos los casos. Por ejemplo, se romperá si su función es código nativo. También los cierres son problemáticos.
El problema real con los objetos y los trabajadores web es con los métodos de esos objetos. Un objeto no debería tener métodos solo propiedades.
Ex:
var myClass = function(){
this.a = 5;
this.myMethod = function(){}
}
var notParseableObject = new myClass();
var myClass2 = function(){
this.a = 5;
}
var parseableObject = new myClass2();
El primero no funcionará (con el mensaje de error mencionado) con postMessage y el segundo funcionará.
Hay algunas razones por las que el error que usted mencionó podría haberse producido, las razones se enumeran aquí .
Cuando se envían objetos a los trabajadores web, el objeto se serializa y luego se deserializa en el trabajador web si el objeto es un objeto serializable.
Esto significa que los métodos para los objetos que envía a su trabajador web no son algo que se pueda pasar al trabajador web (causando el error que ha encontrado), y deberá proporcionar los métodos / funciones necesarios a los objetos. en el lado del entorno del trabajador web, y asegúrese de que no formen parte del objeto que se pasa a los trabajadores web.
Recientemente me encontré con este mismo problema al usar trabajadores web. Todo lo que le pasé a mi trabajador conservaba todas sus propiedades pero misteriosamente perdía todos sus métodos.
Tendrá que definir los métodos en el propio script del trabajador web. Una solución es importScripts
la definición de clase y establecer manualmente la propiedad __proto__
de todo lo que reciba. En mi caso, quería pasar un objeto de grid
, definido en grid.js
(sí, estaba trabajando en 2048), y lo hice así:
importScripts(''grid.js'')
onMessage = function(e) {
e.data.grid.__proto__ = Grid.prototype;
...
}
Echa un vistazo al plugin vkThread
http://www.eslinstructor.net/vkthread/
puede pasar la función a un trabajador, incluida la función con contexto (método del objeto). También puede pasar funciones con dependencias, funciones anónimas y lambdas.
--Vadim