不解决延迟会不会造成内存泄漏?

Will not resolving a deferred create memory leaks?

假设如下代码:

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() 吗?

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

定义回调

我也遇到过这个,Can jQuery deferreds be cancelled?,但是我并没有尝试取消 deferred

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

谢谢,

If I never end up calling resolve() or fail(), will this cause memory leaks, since I keep references in the callbacks?

如果 deferred 变量本身不再可以通过任何代码访问(这也意味着没有其他承诺依赖于此代码),那么它将有资格进行垃圾收集,即使它是从未解决或拒绝。如果您想更详细地了解 "reachable" 的含义,那么您最好展示您关心的实际代码。

另一方面,如果您仍然在某个地方持有 deferred 变量,或者仍然可以访问的其他承诺取决于此承诺(这意味着这些承诺引用了此承诺) , 那么无论延迟对象是否已经被解析,它仍然是活着的,不能被垃圾收集。

Promise 在垃圾回收时只是普通的 Javascript 对象,因此它们遵循与普通对象相同的所有垃圾回收规则。

If I call one, but not the other, will the other be garbage collected? So if I call fail(), will jquery get rid of done().

代码本身不会被垃圾回收。垃圾收集的是变量和对象的内容。因此,在您显示的代码中,垃圾收集的主题是 deferred 变量(变量指向的承诺对象)的内容。而且,正如我上面所说的,无论您已经解决、拒绝还是两者都没有,都没有区别。重要的是您的代码是否仍然可以访问该对象。如果任何代码仍然可以访问 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 的实时事件处理程序,因此它变得无法访问。届时,它将有资格进行垃圾回收。