从来没有解决过承诺导致内存泄漏的问题吗?

我有一个 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?

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

27681 次浏览

Well, I'm assuming you don't keep an explicit reference to it since that would force it to stay allocated.

The simplest test I could think of is actually allocating a lot of promises and not resolving them:

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

And then watching the heap itself. As we can see in the Chrome profiling tools, this accumulates the needed memory to allocate a 100 promises and then just "stays there" at less than 15 megabyes for the whole JSFIddle page

enter image description here

From the other side, if we look at the $q source code

We can see that there is no reference from a global point to any particular promise but only from a promise to its callbacks. The code is very readable and clear. Let's see what if you do however have a reference from the callback to the promise.

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);

enter image description here

So after the initial allocation - it seems like it's able to handle that as well :)

We can also see some interesting patterns of GC if we let his last example run for a few more minutes. We can see that it takes a while - but it's able to clean the callbacks.

enter image description here

In short - at least in modern browsers - you don't have to worry about unresolved promises as long as you don't have external references to them