У меня есть 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
жизненным циклом?
javascript
angularjs
memory-leaks
promise
angular-promise
Умут Бензер
источник
источник
Ответы:
Что ж, я предполагаю, что вы не сохраняете явную ссылку на него, поскольку это заставит его оставаться выделенным.
Самый простой тест, который я мог придумать, - это выделить много обещаний, а не разрешить их:
var $q = angular.injector(["ng"]).get("$q"); setInterval(function () { for (var i = 0; i < 100; i++) { var $d = $q.defer(); $d.promise; } }, 10);
А потом смотрю саму кучу. Как мы видим в инструментах профилирования Chrome, при этом накапливается необходимая память для выделения 100 обещаний, а затем просто «остается там» менее 15 мегабайт для всей страницы JSFIddle.
С другой стороны, если мы посмотрим на
$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);
Итак, после первоначального распределения - похоже, что он тоже может справиться с этим :)
Мы также можем увидеть некоторые интересные паттерны GC, если мы позволим его последнему примеру поработать еще несколько минут. Мы видим, что это занимает некоторое время, но оно может очистить обратные вызовы.
Вкратце - по крайней мере, в современных браузерах - вам не нужно беспокоиться о неразрешенных обещаниях, если у вас нет внешних ссылок на них.
источник
var b = $http.get(...)
или не добавили к нему обратный вызов. Это также имеет ссылку на это. Если что-то разрешает это (как вы сказали - слишком долго, чтобы разрешить, все еще означает разрешение), у него должна быть ссылка на это. Так что да - это не будет GC'd