javascript - una - innerhtml
¿Hay alguna forma de crear elementos DOM en Web Worker? (9)
Entonces, ¿hay alguna forma, que yo no sepa, de crear elementos DOM, fuera del árbol DOM, en un Web Worker?
No.
Por qué no? Me parece que esto no puede crear problemas de concurrencia, ya que la creación de los elementos podría ocurrir en paralelo sin problemas.
No para crearlos, tienes razón. Pero para adjuntarlas al document
principal, tendrían que enviarse a otro lugar (como por ejemplo, blobs) para que el trabajador no pueda acceder a él después. Sin embargo, no hay absolutamente ningún manejo de documentos disponible en WebWorkers .
Creo un elemento DOM para cada línea tan pronto como llegan los datos (en JSON a través de ajax). Luego guardo los elementos en una matriz y solo muestro las líneas que están visibles.
La construcción de más de 500,000 elementos de DOM es una tarea difícil. Intenta crear elementos DOM solo para las líneas que son visibles. Para mejorar el rendimiento y mostrar las primeras líneas más rápido, también puede dividir su procesamiento en unidades más pequeñas y usar tiempos de espera entre ellas. Consulte Cómo detener el intenso bucle de Javascript al congelar el navegador
Contexto: tengo una aplicación web que procesa y muestra enormes archivos de registro. Por lo general, solo tienen unas 100k líneas de longitud, pero pueden ser de hasta 4 millones de líneas o más. Para poder desplazarme por ese archivo de registro (iniciado por el usuario y mediante JavaScript) y filtrar las líneas con un rendimiento decente, creo un elemento DOM para cada línea tan pronto como llegan los datos (en JSON mediante ajax). Esto me pareció mejor para el rendimiento que para construir el HTML en el back-end. Luego guardo los elementos en una matriz y solo muestro las líneas que están visibles.
Para un máximo de 100k líneas, esto solo toma unos pocos segundos, pero cualquier otra cosa lleva hasta un minuto para 500k líneas (sin incluir la descarga). Quería mejorar el rendimiento aún más, así que traté de usar HTML5 Web Workers. El problema ahora es que no puedo crear elementos en un Web Worker, ni siquiera fuera del DOM. Así que terminé haciendo solo la conversión json a HTML en Web Workers y envié el resultado al hilo principal. Allí es creado y almacenado en una matriz. Desafortunadamente, esto empeoró el rendimiento y ahora lleva al menos 30 segundos más.
Pregunta: ¿Hay alguna manera, que yo no sepa, de crear elementos DOM, fuera del árbol DOM, en un Trabajador web? ¿Si no, porque no? Me parece que esto no puede crear problemas de concurrencia, ya que la creación de los elementos podría ocurrir en paralelo sin problemas.
Bien, investigué un poco más con la información que brindó @Bergi y encontré la siguiente discusión en la lista de correo del W3C:
http://w3-org.9356.n7.nabble.com/Limited-DOM-in-Web-Workers-td44284.html
Y el extracto que responde por qué no hay acceso al analizador XML o al analizador DOM en Web Worker:
Usted está asumiendo que ninguno de los códigos de implementación de DOM utiliza ningún tipo de objetos que no sean DOM, alguna vez, o que si esos objetos son completamente seguros para los hilos. Ese no es el caso, al menos en Gecko.
El problema en este caso no es el mismo objeto DOM que se toca en varios hilos. El problema es que dos objetos DOM en hilos diferentes tocan un tercer objeto global.
Por ejemplo, el analizador XML tiene que hacer algunas cosas que en Gecko solo se pueden hacer en el hilo principal (carga DTD, de forma manual, hay algunas otras que he visto anteriormente pero que no recuerdo de forma manual).
Sin embargo, también se menciona una solución alternativa, que es utilizar una implementación de terceros de los analizadores, de los cuales jsdom es un ejemplo. Con esto, incluso tiene acceso a su propio documento por separado.
No hay una forma directa de acceder al DOM a través de Web Workers. Recientemente lancé @ cycle / sandbox, todavía es WIP, pero con la arquitectura Cycle JS es bastante sencillo declarar el comportamiento de UI en Web Worker. El DOM real solo se toca en el hilo principal, pero los detectores de eventos y las actualizaciones DOM se declaran indirectamente en el trabajador, y se envía un objeto de evento sintetizado cuando sucede algo en esos oyentes. Además, es sencillo montar estos componentes cíclicos de espacio aislado uno al lado del otro con componentes de ciclo regulares.
No veo ninguna razón por la cual no puedas construir html strings usando web-workers. Pero tampoco creo que haya un gran impulso en el rendimiento.
Esto no está relacionado con Web-Workers, pero se relaciona con el problema que está tratando de resolver. Aquí hay algo que podría ayudar a acelerar las cosas:
Use DocumentFragments. Agregue elementos a ellos a medida que ingresan los datos, y agregue los fragmentos al DOM en un intervalo (como una vez por segundo). De esta forma, no tiene que tocar el DOM (e incurrir en un redibujado) cada vez que se carga una línea de texto.
Realice la carga en segundo plano y solo analice las líneas cuando el usuario toque la parte inferior del área de desplazamiento.
No, no puede crear elementos DOM en un trabajador web, pero puede crear una función que acepte el mensaje de ese trabajador web, que crea los elementos DOM. Creo que el diseño que buscas es el llamado "array mandril". Y necesitaría combinar eso con el patrón de diseño del trabajador web.
Por lo tanto, no puede crear DOM directamente en un webworker; sin embargo, puede haber otra opción para hacer un poco de procesamiento fuera del hilo principal.
Mira este jsPerf que acabo de crear: http://jsperf.com/dom-construction-obj-vs-str
Esencialmente, podría estar emitiendo POJSO que tienen todos los mismos valores que obtiene de un DOM, y convertirlo en objetos DOM después de recibir el mensaje (esto es lo que hace cuando recupera el HTML, después de todo, los POJSO son un poco más bajos) sobrecarga, en virtud de no requerir más procesamiento de cadenas). De esta forma, incluso podría hacer cosas como emitir oyentes de eventos y cosas así (digamos, prefijando el nombre del evento con ''!'', Y teniendo el mapa de valor en algún argumento de vista proporcionado por la plantilla).
Mientras tanto, sin el analizador DOM disponible, necesitará lo suyo para convertir una plantilla según sea necesario o para compilar una en un formato rápido.
Según https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers , desafortunadamente no hay acceso al DOM de un trabajador web.
Tienes que entender la naturaleza de un webworker. La programación con hilos es difícil , especialmente si está compartiendo memoria; cosas raras pueden suceder JavaScript no está equipado para tratar con ningún tipo de entrelazado de tipo hilo.
El enfoque de los trabajadores web es que no hay memoria compartida . Esto obviamente lleva a la conclusión de que no se puede acceder al DOM.
Tienes un par de antipatrones en tu diseño:
- Crear un objeto DOM tiene una sobrecarga considerable y está creando potencialmente millones de ellos a la vez .
- Intentar que un trabajador web administre el DOM es exactamente para lo que los web workers no son. Hacen todo lo demás para que el ciclo de eventos DOM se mantenga receptivo.
Puede usar un patrón de cursor para desplazarse arbitrariamente por grandes conjuntos de datos.
- DOM publica un mensaje al trabajador con la posición de inicio y el número de líneas solicitadas (cursor).
- El trabajador web accede aleatoriamente a los registros, publica las líneas recuperadas (datos del cursor).
- DOM actualiza un elemento con el evento de respuesta del cursor asincrónico.
De esta forma, el trabajador realiza el trabajo pesado, cuyo ciclo de eventos está bloqueado durante la captura en lugar del DOM, lo que resulta en usuarios felices sin bloqueos que se maravillan de lo suaves que son todas sus animaciones.