不会解决延迟创建内存泄漏?

时间:2015-04-20 19:56:15

标签: jquery deferred

假设以下代码:

var deferred = $.Deferred();
deferred.done(function(){
    // do something with events, references to dom, etc...
});

deferred.fail(function(){
    // do something with events, references to dom, etc...
});
  1. 如果我从未结束调用resolve()fail(),这是否会导致内存泄漏,因为我在回调中保留了引用?

  2. 如果我打电话给另一个,而不打另一个,那么另一个会被垃圾收集吗?所以如果我打电话给fail(),jquery会摆脱done()吗?

  3. 我可能完全错了,但想澄清一下。到目前为止,我找到的最接近的是Shall I always invoke either JQuery Deferred.resolve or Deferred.reject?。但是用例有点不同,因为在该示例中,用户从未为fail()定义回调。

    我也遇到过此问题,Can jQuery deferreds be cancelled?,但我并不想取消deferred

    我知道这不是最佳做法,但出于问题的目的,我仍然很好奇是否会导致记忆问题。

    谢谢,

1 个答案:

答案 0 :(得分:8)

  

如果我从未结束调用resolve()或fail(),这会导致内存   泄漏,因为我在回调中保留了引用?

如果您的任何代码都无法访问deferred变量本身(这也意味着根据此代码没有其他承诺),那么它将有资格进行垃圾回收,即使它从未解决过或拒绝。如果你想了解什么"可达"意味着,最好是展示您关注的实际代码。

另一方面,如果您仍然在某个地方持有deferred变量或其他仍然可以接受的承诺取决于此承诺(这意味着这些承诺会引用此承诺) ,那么延迟对象是否已经解决并不重要,它仍然存在并且不能被垃圾收集。

Promses在垃圾收集方面只是普通的Javascript对象,所以它们遵循与普通对象相同的垃圾收集规则。

  

如果我打电话给另一个,而不是另一个,那么另一个会被垃圾收集吗?   因此,如果我调用fail(),jquery将摆脱done()。

代码本身并没有收集垃圾。它是收集垃圾的变量和对象的内容。因此,在您显示的代码中,它是作为垃圾收集主题的deferred变量(变量指向的promise对象)的内容。而且,正如我上面所说的那样,无论你是否已经解决,拒绝或两者都没有。重要的是,如果您的代码仍然可以访问该对象。如果任何代码仍然可以访问deferred变量,或者任何其他代码或承诺仍然可以访问此承诺。


例如,如果我在页面中有这个顶级代码:

<script>
var deferred = $.Deferred();
deferred.done(function(){
    // do something with events, references to dom, etc...
});
deferred.resolve();
</script>

deferred变量仍然可以访问且仍然存活,因此它指向的Deferred对象不能被垃圾回收。


或者,如果我有这个:

<script>
$("#submit").click(function() {
    var p = $.get(myURL);
    p.done(function(data) {
        if (data) {
            $("#msg").html(data.msg);
        }
    });
});
</script>

然后,只要ajax调用完成并调用.done()处理程序,就不再有任何代码可以访问p变量的实例,因为ajax操作已完成它将释放对promise的引用,因此它不能触发任何更多的promise回调本身。并且,它已经超出了单击处理程序回调函数的范围,并且没有可以访问p的实时事件处理程序,因此它已无法访问。此时,它将有资格进行垃圾收集。