Mam Promise
. Utworzyłem go, aby w razie potrzeby anulować żądanie AJAX. Ale ponieważ nie muszę anulować tego AJAX, nigdy go nie rozwiązałem i AJAX zakończył się pomyślnie.
Uproszczony fragment:
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?
Czy nigdy nie rozwiązane takie obietnice powodują wycieki pamięci? Czy masz jakieś rady dotyczące zarządzania Promise
cyklem życia?
javascript
angularjs
memory-leaks
promise
angular-promise
Umut Benzer
źródło
źródło
Odpowiedzi:
Cóż, zakładam, że nie masz do niego wyraźnego odniesienia, ponieważ zmusiłoby to go do pozostania przydzielonym.
Najprostszym testem, jaki przychodzi mi do głowy, jest przydzielanie wielu obietnic, a nie ich rozwiązywanie:
var $q = angular.injector(["ng"]).get("$q"); setInterval(function () { for (var i = 0; i < 100; i++) { var $d = $q.defer(); $d.promise; } }, 10);
A potem oglądanie samej sterty. Jak widać w narzędziach do profilowania Chrome, gromadzi to pamięć potrzebną do przydzielenia 100 obietnic, a następnie po prostu „pozostaje tam” przy mniej niż 15 megabajtach dla całej strony JSFIddle
Z drugiej strony, jeśli spojrzymy na
$q
kod źródłowyWidzimy, że nie ma odniesienia z punktu globalnego do żadnej konkretnej obietnicy, ale tylko z obietnicy do jej wywołań zwrotnych. Kod jest bardzo czytelny i przejrzysty. Zobaczmy, co się stanie, jeśli jednak masz odniesienie z wywołania zwrotnego do obietnicy.
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);
Więc po wstępnej alokacji - wygląda na to, że sobie z tym poradzi :)
Możemy również zobaczyć kilka interesujących wzorów GC, jeśli pozwolimy, aby jego ostatni przykład działał jeszcze przez kilka minut. Widzimy, że zajmuje to trochę czasu - ale jest w stanie wyczyścić wywołania zwrotne.
Krótko mówiąc - przynajmniej w nowoczesnych przeglądarkach - nie musisz się martwić o nierozwiązane obietnice, o ile nie masz do nich zewnętrznych odniesień
źródło
var b = $http.get(...)
lub dodasz do niej callback. To również ma odniesienie do tego. Jeśli coś go rozwiązuje (tak jak powiedziałeś - zbyt długi czas na rozwiązanie nadal oznacza rozwiązanie) - musi mieć do tego odniesienie. Więc tak - to nie będzie GC'd