Bem, presumo que você não mantenha uma referência explícita a ele, pois isso o forçaria a permanecer alocado.
O teste mais simples que eu poderia pensar é realmente alocar um monte de promessas e não resolvê-las:
var $q = angular.injector(["ng"]).get("$q");
setInterval(function () {
for (var i = 0; i < 100; i++) {
var $d = $q.defer();
$d.promise;
}
}, 10);
E então observando a própria pilha. Como podemos ver nas ferramentas de criação de perfil do Chrome, isso acumula a memória necessária para alocar 100 promessas e então apenas "permanece lá" com menos de 15 megabyes para toda a página JSFIddle
Por outro lado, se olharmos para o $q
código-fonte
Podemos ver que não há referência de um ponto global a qualquer promessa em particular, mas apenas de uma promessa a seus retornos de chamada. O código é muito legível e claro. Vamos ver se você, entretanto, tem uma referência do retorno de chamada para a promessa.
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);
Portanto, após a alocação inicial - parece que também é capaz de lidar com isso :)
Também podemos ver alguns padrões interessantes de GC se deixarmos seu último exemplo rodar por mais alguns minutos. Podemos ver que demora um pouco - mas é capaz de limpar os callbacks.
Resumindo - pelo menos nos navegadores modernos - você não precisa se preocupar com promessas não resolvidas, desde que não tenha referências externas a elas