永远不会解决的承诺导致内存泄漏?

Umu*_*zer 85 javascript memory-leaks promise angularjs angular-promise

我有一个Promise.我创建它以在需要时取消AJAX请求.但是因为我不需要取消那个AJAX,所以我从未解决它并且AJAX成功完成.

一个简化的片段:

var defer = $q.defer();
$http({url: 'example.com/some/api', timeout: defer.promise}).success(function(data) {
    // do something
});

// Never defer.resolve() because I don't need to cancel that ajax. What happens to this promise after request?
Run Code Online (Sandbox Code Playgroud)

永远不会解决这样的承诺导致内存泄漏?您对如何管理Promise生命周期有什么建议吗?

Ben*_*aum 142

好吧,我假设你没有明确提到它,因为这会迫使它保持分配.

我能想到的最简单的测试实际上是分配了许多承诺而没有解决它们:

var $q = angular.injector(["ng"]).get("$q");
setInterval(function () {
    for (var i = 0; i < 100; i++) {
        var $d = $q.defer();
        $d.promise;
    }
}, 10);
Run Code Online (Sandbox Code Playgroud)

然后看着堆本身.正如我们在Chrome分析工具中看到的那样,这会累积所需的内存以分配100个承诺,然后只需"保持在那里",整个JSFIddle页面的内容小于15兆字节

在此输入图像描述

从另一方面来看,如果我们看一下$q源代码

我们可以看到,从全局角度来看,没有任何特定承诺的参考,只能来自对其回调的承诺.代码非常易读且清晰.让我们看看如果你做了什么但是从回调到承诺的引用.

var $q = angular.injector(["ng"]).get("$q");
console.log($q);
setInterval(function () {
    for (var i = 0; i < 10; i++) {
        var $d = $q.defer();
        (function ($d) { // loop closure thing
            $d.promise.then(function () {
                console.log($d);
            });
        })($d);
    }
}, 10);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

所以在初始分配之后 - 似乎它也能够处理它:)

如果我们让他的最后一个例子运行几分钟,我们也可以看到一些有趣的GC模式.我们可以看到它需要一段时间 - 但它能够清理回调.

在此输入图像描述

简而言之 - 至少在现代浏览器中 - 只要您没有对它们的外部引用,您就不必担心未解决的承诺

  • 这些评论中有一些道理,有些是误导性的,所以让我澄清一下:附带处理程序的承诺*可能*有资格进行垃圾收集.如果以下***满足以下条件,则承诺保持活动(不符合GC条件):( 1)对promise对象有引用,(2)对promise的"延迟"状态有引用(用于解析/拒绝它的对象/函数).除此之外,承诺符合GC的条件.(如果没有人有承诺,任何人都无法改变其状态,那么它的目的又是什么呢?) (7认同)
  • 这是不是意味着如果一个承诺需要太长时间才能解决(但最终会*解决),那么它是否有被GC风险的风险? (5认同)
  • @ w.brian除非你把它分配到某个地方 - 比如变量:`var b = $ http.get(...)`或者给它添加一个回调.这也是对它的引用.如果有什么东西可以解决它(就像你说的那样 - 太长时间无法解决仍然意味着解决) - 它必须有一个引用它.所以是的 - 它不会是GC的 (3认同)
  • 知道了,这就是我的想法.所以,问题是"永远不会解决承诺会导致内存泄漏吗?" 对于将回调传递给promise的常见用例,答案是肯定的.你的答案中的这一行似乎与之相反:"如果我们让他的最后一个例子运行几分钟,我们也可以看到一些有趣的GC模式.我们可以看到它需要一段时间 - 但它能够清理回调. " 对不起,如果我是迂腐和挑剔,我只是想确保我理解这一点. (3认同)