Red de conocimiento informático - Material del sitio web - Cómo evitar pérdidas de memoria al personalizar los widgets de Dojo

Cómo evitar pérdidas de memoria al personalizar los widgets de Dojo

Durante las pruebas, descubrí que muchos widgets personalizados no liberaban los subwidgets que contenían cuando se destruyeban. Además, se puede hacer referencia a estas instancias de widgets inéditas ejecutando la función dojo.byId en la consola de Firebug. Esto puede provocar graves pérdidas de memoria. Para resolver este problema, leí el código, probé el proceso de destrucción de los widgets de Dojo y resumí varias reglas que se deben seguir al escribir widgets personalizados. Quiero compartir los resultados contigo aquí. Volver arriba Utilice el complemento Firebug Dojo para monitorear pérdidas de memoria FireBug es un complemento de navegador desarrollado basado en el navegador FireFox. El propio FireBug admite muchos complementos, y el complemento Dojo que vamos a utilizar es uno de los complementos de Firebug. El complemento Dojo proporciona las siguientes funciones: Ver todos los widgets registrados Ver información de la versión de Dojo, información del módulo Dojo, número total de widgets, conexiones y suscripciones totales Ver información detallada de conexión y suscripción Establecer puntos de interrupción en el procesamiento de conexión y suscripción Abrir ayuda del widget Documentación Nosotros Puede saber si hay una pérdida de memoria observando el número total de widgets (cree un widget personalizado y luego destrúyalo; si el número total de widgets aumenta, significa que los subwidgets contenidos en el widget personalizado no se han eliminado). liberado). Volver al principio Análisis del proceso de destrucción de widgets La mayoría de los widgets personalizados que creamos en el proyecto heredan de los widgets dijit._Widget y dijit._Templated. Entre ellos, la clase dijit._Templated es una clase híbrida que guarda puntos de conexión y matrices de eventos adjuntos y los libera en el método destroyRendering. La clase dijit._Widget no define un método de destrucción, pero su clase principal dijit._WidgetBase tiene una serie de métodos para destruir sus propias instancias, que deben analizarse cuidadosamente, como se muestra en la siguiente tabla. Tabla 1. Método de destrucción dijit._WidgetBase Nombre del método Descripción destroyRecursive Destruye este widget y sus descendientes destroy Destruye este widget, pero no sus descendientes destruye los hijos de este widget y sus descendientes. Función de código auxiliar de desinicialización. Análisis del método destroyRecursive Primero, echemos un vistazo al método destroyRecursive. De los comentarios en el código Dojo, podemos ver que es el punto de entrada general para el proceso de destrucción. El código es el siguiente: Listado 1._WidgetBase método destroyRecursive this._beingDestroyed = true; this.destroyDescendants(preserveDom); this.destroy(preserveDom); destruirDescendientes El widget luego se destruye a sí mismo llamando a destruir. Análisis del método destroyDescendants Veamos primero la función del método destroyDescendants.

Mire el código a continuación: Listado 2._WidgetBase método destroyDescendants dojo.forEach(this.getChildren(), function(widget) { if(widget.destroyRecursive) { widget.containerNode como nodo raíz y use dijit.findWidgets para buscar y obtenga la lista de widgets. Hagamos un experimento y creemos un control personalizado: MemoryLeakTest hereda de dijit._Widget y dijit._Templated. El código de la plantilla es el siguiente: Listado 3. Plantilla de widget MemoryLeakTest. Tengo un punto de conexión. Tengo un sub del punto de conexión. El código sub js solo define dos métodos: Listado 4 El código js de la parte del gadget MemoryLeakTest addContentPane: function() { var temp=new dijit.layout.ContentPane({id: "memoryLeakTest" . ")contentPane({id: "dcd "}); this.domNode.appendChild(temp.domNode); }, listChildren: function() { dojo.forEach(this.getChildren(), function(widget){ console.log ("Widget: " widget.get( "id")); } } En la página de prueba, llamamos al método listChildren directamente y no hay salida en la consola. A través de firebug, podemos rastrear el nodo contenedor de. el widget actual es igual a nulo. Sobrecarguemos el método buildRendering y en este método, a containerNode se le asigna un valor: this.containerNode=this.domNode, luego se llama a listChildren y podemos ver los ID de varios subwidgets; A partir de esto, podemos resumir varias reglas a las que se debe prestar atención al escribir widgets personalizados: Asignar un valor a containerNode Generalmente, asignamos domNode a containerNode. Ya existen operaciones correspondientes en dijit._Container. puedes heredar esta clase. Si tiene necesidades especiales y no puede configurar contenedorNode en domNode, puede llamar usted mismo al método destroyRecursive del widget secundario ubicado fuera de contenedorNode. Análisis del método de destrucción A continuación, echemos un vistazo a lo que se hace en el método de destrucción.

Listado 5. Método de destrucción _WidgetBase this._beingDestroyed = true; this.uninitialize(); var d = dojo, dfe = d.forEach, dun = d.unsubscribe; d.disconnect); }); dfe(this.dfe(this._subscribes, function(handle) { dun(handle); }); // destruye los widgets creados como parte de la plantilla, etc. dfe(this._supportingWidgets || [], función(w) { if(w.destroyRecursive) { w.destroyRecursive(); }si no (w.destroy) { w.destroy( } }; handle }); this.destroyRendgets, function(handle) { dun(handle }); // destruye los widgets creados como parte de la plantilla, etc.}); (this.id); this._destroyed = true; Podemos ver que la segunda línea del Listado 5 llama al método uninitialize de dijit._WidgetBase. Este es un método virtual. En este método, debemos liberar los recursos recopilados durante la creación y el uso del widget (por ejemplo, desreferenciar el objeto de propiedad, borrar los objetos en la propiedad de tipo de matriz, etc.). Las líneas 6 a 11 del Listado 5 logran dos cosas: dojo.disconnect en cada elemento de la matriz _connects y dojo.unsubscribe en cada elemento de la matriz _subcribes. A través del resto del código _WidgetBase, sabemos que estas dos matrices almacenan los identificadores obtenidos a través de dojo.connect (en el método this.connect) y dojo.subscribe (en el método this.subscribe). A partir de esto, podemos derivar algunas reglas adicionales a tener en cuenta al escribir widgets personalizados: Sobrecargue el método uninitialize para liberar recursos. Utilice el método this.connect en lugar de dojo.connect. Utilice el método this.subscribe en lugar de dojo.subscribe. Volver arriba Del análisis anterior podemos ver que al personalizar los widgets de Dojo, podemos evitar fácilmente pérdidas de memoria innecesarias siguiendo las siguientes reglas. Asigne un valor a containerNode. En términos generales, cuando asignamos domNode a containerNode, ya existen operaciones correspondientes en dijit._Container. Si es necesario, puede heredar de esta clase.

Si tiene necesidades especiales y no puede configurar contenedorNode en domNode, llame al método destroyRecursive del componente secundario ubicado fuera de contenedorNode. Sobrecargue el método de desinicialización para liberar recursos. Utilice el método this.connect en lugar de dojo.connect. Utilice el método this.subscribe en lugar de dojo.subscribe. Referencias Referencias de aprendizaje GetFireBug.com: sitio web oficial de FireBug.

Guía de referencia de DojoFirebugExtension: Descripción detallada y manual de referencia del complemento FireBug Dojo.

Kit de herramientas de referencia de Dojo: código fuente de Dojo y documentación de ayuda.

desarrollo web developmentWorks: amplíe sus habilidades de desarrollo web con artículos y tutoriales dedicados a las tecnologías web.

Centro de recursos de DeveloperWorks Ajax: este es un centro integral de información sobre el modelo de programación Ajax, que incluye documentación extensa, tutoriales, foros, blogs, wikis y noticias. Cualquier información nueva sobre Ajax se puede encontrar aquí.

El Centro de recursos Web 2.0 de DeveloperWorks es su fuente única de información sobre Web 2.0, que incluye una amplia gama de artículos técnicos, tutoriales, descargas y recursos técnicos relacionados sobre Web 2.0. También puede obtener una introducción rápida a los conceptos de la Web 2.0 en la sección Introducción a la Web 2.0.

Consulte el tema HTML5 para obtener más información sobre HTML5 y las tendencias.

Discute cómo unirte a la comunidad de developmentWorks.

Discute cómo unirte a la comunidad china de DeveloperWorks.