在javascript中关闭和回调内存泄漏

Iva*_*gin 18 javascript closures memory-leaks node.js

function(foo, cb) {
  var bigObject = new BigObject();
  doFoo(foo, function(e) {
     if (e.type === bigObject.type) {
          cb();
          // bigObject = null;
     }
  });
}
Run Code Online (Sandbox Code Playgroud)

上面的例子显示了一个经典的,偶然的(或可能没有)内存泄漏的闭包.V8垃圾收集器无法确定是否可以安全删除bigObject它,因为它在回调函数中被使用,可以多次调用.

一种解决方案是设置bigObjectnull回调函数中的作业何时结束.但是如果你使用了很多变量(想象有n变量之类的bigObject,并且它们都在回调中使用)那么清理它就成了一个难看的问题.

我的问题是:有没有其他方法可以清理那些使用过的变量?

编辑这是另一个(现实世界)的例子:所以我从mongodb获得应用程序并将其与其他应用程序进行比较.来自mongodb的回调使用从该回调中定义的变量应用程序.从mongodb得到结果后,我还将它作为回调返回(因为它都是异步的,我不能写回程).所以实际上我可以将回调一直传播到源...

function compareApplications(application, condition, callback) {

    var model = database.getModel('Application');
    model.find(condition, function (err, applicationFromMongo) {
        var result = (applicationFromMongo.applicationID == application.applicationID)
        callback(result)        
    }
}
Run Code Online (Sandbox Code Playgroud)

Bra*_*don 2

如果您的回调函数只应该被调用一次,那么您应该在调用后取消订阅。这将释放你的回调 + GC 的闭包。随着您的关闭被释放,bigObjectGC 也可以免费收集。

这是最好的解决方案 - 正如您所指出的,GC 不会神奇地知道您的回调只会被调用一次。

  • 问题是我不知道如何在这个特定问题中取消注册回调!正如我所说,我使用node.js,并且没有绑定到像jQuery或类似的事件,我只是将回调函数传递给另一个函数(本例中为doFoo),并且doFoo执行一些IO操作,然后在我传递的某个点调用回调函数。 (3认同)
  • 感谢您的回答,但是您能举一些取消订阅回调的示例吗? (2认同)