2013-11-19 4 views
65

У меня есть обещание. Я создал его, чтобы отменить запрос AJAX, если мне нужно. Но поскольку мне не нужно отменять этот AJAX, я никогда не разрешал его, и AJAX завершил успешно.Никогда не разрешали обещания вызывать утечку памяти?

упрощенный sinippet:

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? 

У нераскрытого обещания, как, что утечки памяти причины? У вас есть какие-либо советы о том, как управлять жизненным циклом обещаний?

ответ

123

Ну, я предполагаю, что вы не держите явной ссылки на него, поскольку это заставит его оставаться выделенным.

Самый простой тест, который я мог думать на самом деле распределения много обещаний и не решить их:

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 megabyes для всей JSFIddle page

enter image description here

С другой стороны, если мы посмотрим на $q source code

Мы можем видеть, что нет ссылки с глобальной точки на какие-либо конкретные обещания, а только на обещание ее обратных вызовов. Код очень читабельны и понятны. Посмотрим, что, если у вас все же есть ссылка от обратного вызова к обещанию.

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

Таким образом, после первоначального распределения - кажется, что он в состоянии справиться с этим, а также :)

Мы также можем увидеть некоторые интересные модели GC, если мы позволим его последний пример перспективе еще несколько минут. Мы видим, что это занимает некоторое время, но он способен очищать обратные вызовы.

enter image description here

Короче - по крайней мере в современных браузерах - вам не придется беспокоиться о неразрешенных обещании до тех пор, пока вы не имеете внешние ссылки на них

+8

большого ответа !!! –

+2

Разве это не означает, что если обещание слишком долго для решения (но в конечном итоге будет разрешено), это может быть GC'd? –

+0

@ w.brian Я написал: «Я предполагаю, что вы не держите явной ссылки на него, поскольку это заставит его оставаться выделенным». Как вы думаете, я должен прояснить это? (ps вы не подвергаетесь риску) –