小程序页面A 通过<navigate>跳转到页面B。
页面B通过小程序自带的顶部返回按钮,返回页面A。
重复A到B,B返回A 操作。
小程序就有可能卡死。
A页面内容仅<navigate>标签。B页面仅几个表单字段。B返回A,并未做表单提交。
调试工具还有一个报错异常:
(node) warning: possible EventEmitter memory leak detected. 16 listeners added. Use emitter.setMaxListeners() to increase limit.
内存泄漏(Memory Leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。
导致内存泄漏的原因:
① 全局变量:全局变量直接挂在 root 对象上,不会被清除掉
a = 10;//未声明对象。
global.b = 11;//全局变量引用
② 闭包:闭包会引用到父级函数中的变量,如果闭包未释放,就会导致内存泄漏。上面例子是 inner 直接挂在了 root 上,那么每次执行 out 函数所产生的 bigData 都不会释放,从而导致内存泄漏。
function out() {
const bigData = new Buffer(100);
inner = function () {
void bigData;
}
}
③ 事件监听:Node.js 的事件监听也可能出现的内存泄漏。例如对同一个事件重复监听,忘记移除(removeListener),将造成内存泄漏。这种情况很容易在复用对象上添加事件时出现,所以事件重复监听可能收到如下警告:
(node:2752) Warning: Possible EventEmitter memory leak detected。11 haha listeners added。Use emitter。setMaxListeners() to increase limit
1
④其他原因:还有一些其他的情况可能会导致内存泄漏,比如缓存、非常占用 CPU 的代码等。
虽然只是警告,但有时候会影响到其他事件的执行,且,控制台上存在标红时,相信每一个程序员的心里应该都是不太舒服的。
避免内存泄漏方式:
① ESLint 检测代码检查非期望的全局变量。
② 使用闭包的时候,得知道闭包了什么对象,还有引用闭包的对象何时清除闭包。最好可以避免写出复杂的闭包,因为复杂的闭包引起的内存泄漏,如果没有打印内存快照的话,是很难看出来的。
③ 绑定事件的时候,一定得在恰当的时候清除事件。在编写一个类的时候,推荐使用 init 函数对类的事件监听进行绑定和资源申请,然后 destroy 函数对事件和占用资源进行释放。
解决方法:
const emitter = new EventEmitter()
emitter.setMaxListeners(100)//指定一个最大监听数量
emitter.setMaxListeners(0)//或者关闭最大监听阈值