Using dijit/Destroyable to build safe Components
In today's long-lived JavaScript apps it is essential to not introduce memory leaks within your custom components. Dojo Toolkit to the rescue: The dijit/Destroyable module addresses this problem and makes it really easy to track the various handles of an instance. Various components such as dojo/aspect, dojo/topic, dojo/on, dojo/Stateful and dojo/store/Observable return a handle which can be passed to dijit/Destroyable's own() method. The application must then call destroy() on the instance in order to release the handles.
Here's an example demonstrating the tracking of some handles and how to have them removed at the end of the components lifecycle:
Our layout
+ source.html
+ mylib
+ app.js
+ ChildWidget.js
+ MainWidget.js
+ templates
+ MainWidget.html
MainWidget.js
This is the main widget which makes use of events, aspects, topics etc. It tracks all its handles by passing them to own():
define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/aspect",
"dojo/topic",
"dojo/on",
"dojo/Stateful",
"dojo/store/Memory",
"dojo/store/Observable",
"./ChildWidget",
"dojo/text!./templates/MainWidget.html"
], function (
declare,
WidgetBase,
TemplatedMixin,
aspect,
topic,
on,
Stateful,
Memory,
Observable,
ChildWidget,
template
) {
return declare([WidgetBase, TemplatedMixin], { templateString: template, // constructor args
timeout: null,
leaky: false, postCreate: function () {
this.setChildWidget();
this.setAspect();
this.setEvent();
this.setSubscription();
this.setStateful();
this.setObservable();
}, setChildWidget: function () {
var widget = new ChildWidget({ timeout: this.timeout }); if(!this.leaky) {
// register widget.destroy() to be called when this widget is destroyed
this.own(widget);
}
}, setAspect: function () {
var someObject = {
someMethod: function () {}
}, signal = aspect.after(someObject, 'someMethod', function () {
console.warn('aspect.after');
}); if(!this.leaky) {
// register signal.remove() to be called when this widget is destroyed
this.own(signal);
} // call someObject.someMethod() after this widget has been destroyed
setTimeout(function() {
someObject.someMethod();
}, this.timeout);
}, setEvent: function () {
var handle = on(this.clickableNode, 'click', function (ev) {
console.warn('on');
}); if(!this.leaky) {
// register handle.remove() to be called when this widget is destroyed
this.own(handle);
}
}, setSubscription: function () {
var subscription = topic.subscribe('some-topic', function (data) {
console.warn('topic.subscribe');
}); if(!this.leaky) {
// register subscription.remove() to be called when this widget is destroyed
this.own(subscription);
} // publish a topic after this widget has been destroyed
setTimeout(function() {
topic.publish('some-topic', {});
}, this.timeout);
}, setStateful: function () {
var stateful = new Stateful({ a: 'aaa' }), handle = stateful.watch('a', function (name, oldVal, newVal) {
console.warn('Stateful');
}); if(!this.leaky) {
// register handle.remove() to be called when this widget is destroyed (handle.unwatch() is deprecated)
this.own(handle);
} // modify a property after this widget has been destroyed
setTimeout(function() {
stateful.set('a', 'AAA');
}, this.timeout);
}, setObservable: function () {
var store = Observable(new Memory({
data: [{ id: 0, a: 'aaa' }]
})), result = store.query(), observer = result.observe(function (item, removedIndex, insertedIndex) {
console.warn('Observable');
}, true); if(!this.leaky) {
// register observer.remove() to be called when this widget is destroyed (observer.cancel() is deprecated)
this.own(observer);
} // add an item after this widget has been destroyed
setTimeout(function() {
store.put({ id: 1, b: 'bbb' });
}, this.timeout);
}
});
});
ChildWidget.js
A widget without DOM representation:
define([
"dojo/_base/declare",
"dijit/_WidgetBase"
], function (
declare,
WidgetBase
) {
return declare([WidgetBase], { timeoutId: null, // constructor args
timeout: null, postCreate: function () {
this.timeoutId = setTimeout(function () {
console.warn('child widget');
}, this.timeout);
}, destroy: function () {//alert('destroy')
this.inherited(arguments);
clearTimeout(this.timeoutId);
}
});
});
app.js
The entry point into the application:
define([
"./MainWidget",
"dojo/domReady!"
], function (MainWidget) { var timeout = 3000, widget = new MainWidget({
timeout: timeout,
leaky: false // this is just to demonstrate the behaviour of a leaky widget
}, 'widget'); widget.startup(); setTimeout(function () {
widget.destroy(true);
console.info('Widget is now destroyed while preserving the dom')
}, timeout - 1000); // destroy widget one second before the various potentially leaky handles in the widget are executed
});
source.html
... and finally the HTML page to bootstrap our application:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Destroyable</title>
<script>
var dojoConfig = {
async: true,
cacheBust: 1,
packages: [
{ name: 'mylib', location: 'path/to/mylib' } // relative to dojo/dojo.js
]
};
console.log('SOURCE');
</script> <script src="path/to/dojo/dojo.js"></script><!-- relative to this document --> <script>
require(['mylib/app']);
</script>
</head>
<body>
<div class="document">
<div id="widget"></div>
</div>
</body>
</html>
Using dijit/Destroyable to build safe Components的更多相关文章
- [Recompose] Configure Recompose to Build React Components from RxJS Streams
Recompose provides helper functions to stream props using an Observable library of your choice into ...
- 5、二、App Components(应用程序组件):0、概述
二.App Components(应用程序组件) 0.概述 App Components Android's application framework lets you create rich ...
- Open Harmony移植:build lite配置目录全梳理
摘要:本文主要介绍build lite 轻量级编译构建系统涉及的配置目录的用途,分析相关的源代码. 本文分享自华为云社区<移植案例与原理 - build lite配置目录全梳理>,作者:z ...
- 转:分享13款PHP开发框架
文章来自于:http://mashable.com/2014/04/04/php-frameworks-build-applications/ Building software applicatio ...
- 安装MySQL的时候遇到的错误
这里我安装的是MySQL5.6 我遇到的错误有 (1)Warning: Bison executable not found in PATH 解决办法: yum install bison 原文摘自: ...
- REACT day 1
https://facebook.github.io/react/ A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES Declarative view ...
- 《静静的dojo》 总体教程介绍
web2.0时代,ajax技术成为整个前端开发领域的基石.大部分的书籍.博客由此切入来介绍前端类库与框架,所以dojo往往只被当做一个ajax类库来介绍,然而仅仅以此来定位dojo,无异于管中窥豹.对 ...
- centos 7.0 编译安装mysql 5.6.22 再次总结 成功编译安装~ 越来越熟练了~
查找php.ini文件所在位置 [root@localhost /]# find -name php.ini ./usr/etc/php/etc/php.ini mysql官网的安装说明http:// ...
- centos6.5环境源码编译安装mysql5.6.34
centos6.5环境源码编译安装mysql5.6.34 源码下载地址http://dev.mysql.com/downloads/mysql/5.6.html#downloads 选择Generic ...
随机推荐
- (45) Manifest文件
这个是一模块主要描述和设置的文件,下面进行讲解一下{ 'name': "A Module", 'version': '1.0', 'depends': ['bas ...
- 关于android的@TargetApi和@SuppressLint("NewApi")
看别人的代码好多地方用到了@TargetApi.以前一直不知道这个是什么意思.后面偶然看了下sdk.才有所明白. 其实这个东西就是在你使用了android Lint检查工具的时候,为了防止代码出现提示 ...
- 通过页面调用APP【H5与APP互通】
现在H5和App原生的内容原来越互通,所涉及的业务也越来越复杂和融合,所以如何互相之间方便的调用才是王道. 场景1 比如用hybrid获取地理位置和短信信息,这当然需要框架封装好,比如利用框架的bri ...
- 转网页WB.ExecWB控件打印方法
网页WB.ExecWB控件打印方法 2010-02-01 12:48 代码: <table width="100%" cellpadding="1" on ...
- 网站指纹识别工具——WhatWeb v0.4.7发布
WhatWeb是一款网站指纹识别工具,主要针对的问题是:“这个网站使用的什么技术?”WhatWeb可以告诉你网站搭建使用的程序,包括何种CMS系统.什么博客系统.Javascript库.web服务 ...
- 深入浅出Mybatis系列(七)---mapper映射文件配置之insert、update、delete
上篇文章<深入浅出Mybatis系列(六)---objectFactory.plugins.mappers简介与配置>简单地给mybatis的配置画上了一个句号.那么从本篇文章开始,将会介 ...
- Java: IO 学习小结
源: 键盘 System.in 硬盘 FileStream 内存 ArrayStream 目的: 控制台 System.out 硬盘 FileStream 内存 ArrayStream 处理大文件或者 ...
- Practical Malware Analysis里有关inetsim\APATEDNS
以前从未接触过linux,碰到了许多问题,按步骤: 1\安装VMWARE,安装ubuntu16.04 问题1:之前装的是VM10,装完后没有安装VMTOOLS,我点安装 VMTOOLS,它弹出“简易安 ...
- iOS版本更新的App提交审核流程
App的版本更新估计是在所难免的了!更新App和新的App发布有何不同了?今天我们一起来看看吧!在发布App的时候我们需要通过开发者帐号——(申请)——>发布证书(需要钥匙串对证书签名也叫加密( ...
- k8s volume
只有nfs和rbd的,本人翻译确实很渣 在容器中磁盘文件寿命是短暂的,当在容器中运行一些重要程序时,这会产生一些问题. 首先,当一个容器崩溃后,kubelet将重新启动该容器, ...