Asla çözülmemiş sözler bellek sızıntısına neden olmaz mı?


92

Bir Promise. Gerekirse bir AJAX isteğini iptal etmek için oluşturdum. Ancak bu AJAX'ı iptal etmem gerekmediğinden, bunu hiçbir zaman çözmedim ve AJAX başarıyla tamamlandı.

Basitleştirilmiş bir snippet:

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?

Bunun gibi asla çözülmemiş vaatler bellek sızıntılarına neden olmaz mı? PromiseYaşam döngüsünü nasıl yöneteceğiniz konusunda herhangi bir tavsiyeniz var mı?


4
"Asla çözülmemiş" bir söz yine de "reddedilebilir". Aradığınız kelime "yerine getirilmedi".
Steven Vachon

$ http ilginç bir örnektir, çünkü sonunda bir HTTP isteği zaman aşımına uğrayacaktır (veya aksi takdirde bir hata yanıtı verir), eğer istemci sunucuya ulaşamazsa, 'zaman aşımı' argümanına aktarılan söz ne olursa olsun.
ryanwebjackson

Yanıtlar:


145

Pekala, sanırım ona açık bir atıfta bulunmazsınız, çünkü bu onu ayrılmış kalmaya zorlar.

Aklıma gelen en basit test aslında birçok söz vermek ve bunları çözmemek:

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

Ve sonra yığının kendisini izliyor. Chrome profil oluşturma araçlarında görebileceğimiz gibi, bu, 100 söz ayırmak için gerekli belleği biriktirir ve ardından tüm JSFIddle sayfası için 15 megabaytın altında "orada kalır".

görüntü açıklamasını buraya girin

Diğer taraftan, kaynak koduna bakarsak$q

Küresel bir noktadan belirli bir söze referans olmadığını, yalnızca bir sözden geri aramalarına referans olduğunu görebiliriz. Kod çok okunabilir ve anlaşılır. Bakalım geri aramadan söze bir referansınız varsa.

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

görüntü açıklamasını buraya girin

Yani ilk tahsisattan sonra - bunu da halledebilecek gibi görünüyor :)

Son örneğinin birkaç dakika daha çalışmasına izin verirsek, bazı ilginç GC kalıplarını da görebiliriz. Biraz zaman aldığını görebiliriz - ancak geri aramaları temizleyebilir.

görüntü açıklamasını buraya girin

Kısacası - en azından modern tarayıcılarda - bunlara dışarıdan referansınız olmadığı sürece çözülmemiş vaatler hakkında endişelenmenize gerek yok


8
Bu, bir sözün çözülmesi çok uzun sürerse (ama sonunda çözülürse), GC'de kalma riski altında olduğu anlamına gelmez mi ?
w.brian

6
@ w.brian, bir yere atamadığınız sürece - örneğin bir değişkene: var b = $http.get(...)veya ona bir geri arama eklemediğiniz sürece. Bunun da bir referansı var. Eğer bir şey onu çözerse (dediğin gibi - çözemeyecek kadar uzun olması hala çözüm anlamına gelir) - ona referans vermesi gerekir. Yani evet - GC'd olmayacak
Benjamin Gruenbaum

3
Anladım, ben de öyle düşündüm. Öyleyse soru şu: "Hiçbir zaman çözülmemiş sözler bellek sızıntısına neden olmaz mı?" Söze bir geri aramanın iletildiği yaygın kullanım durumu için cevap evettir. Cevabınızdaki bu satır şununla çelişiyor gibi görünüyor: "Son örneğinin birkaç dakika daha çalışmasına izin verirsek, GC'nin bazı ilginç kalıplarını da görebiliriz. Biraz zaman aldığını görebiliriz - ancak geri aramaları temizleyebilir. " Bilgiçlik taslayan ve seçici davranıyorsam özür dilerim, sadece bunu anladığımdan emin olmaya çalışıyorum.
w.brian

1
Bu bana mantıklı gelmiyor. 100.000 vaatler oluşturmuş olsaydım, console.log () 'un bir satırı vardı. Bir sihirle aniden çözülürlerse o 100.000'in bu satırları kaydetmesini istiyorum. Ya da tarayıcının bunun asla çözülmeyeceğini bileceğini mi söylüyorsunuz , çünkü ne ben ne de gerçek tarayıcının buna herhangi bir referansı yoktur (hiçbir şey onu etkilemez) - peki bu nasıl olabilir? (hmm, bunun doğru olabileceğini görebiliyorum)
odinho - Velmont

9
Bu yorumlarda bazı gerçekler var ve bazıları yanıltıcı, bu yüzden açıklığa kavuşturmama izin verin: İşleyiciler eklenmiş bir söz, çöp toplama için uygun olabilir . Aşağıdakilerden herhangi biri doğruysa , bir söz canlı tutulur (GC'ye uygun değildir) : (1) taahhüt edilen nesneye bir referans varsa, (2) sözün "ertelenmiş" durumuna bir referans varsa (nesne / çözmek / reddetmek için kullandığınız işlevler). Bunun dışında söz, GC için uygundur. (Kimsenin sözü yoksa ve hiç kimse durumunu değiştiremiyorsa, artık amacı nedir?)
cdhowie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.