क्या कभी हल नहीं किया गया वादा स्मृति रिसाव का कारण बनता है?


91

मेरे पास ए 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जीवन चक्र का प्रबंधन करने के बारे में कोई सलाह है?


4
एक "कभी हल नहीं किया गया" वादा अभी भी "अस्वीकार" किया जा सकता है। आप जिस शब्द की तलाश कर रहे थे वह "अधूरा" था।
स्टीवन वाचोन

$ http एक दिलचस्प उदाहरण है क्योंकि अंततः एक HTTP अनुरोध टाइमआउट (या अन्यथा एक त्रुटि प्रतिक्रिया देगा), यदि क्लाइंट सर्वर तक नहीं पहुंच सकता है, भले ही 'टाइमआउट' तर्क पारित किए गए वादे की परवाह किए बिना।
रयानबजैकसन

जवाबों:


144

ठीक है, मैं मान रहा हूँ कि आप इसके बारे में कोई स्पष्ट संदर्भ नहीं रखते हैं क्योंकि यह इसे आवंटित रहने के लिए मजबूर करेगा।

सबसे सरल परीक्षण जो मैं सोच सकता था कि वास्तव में बहुत सारे वादे आवंटित कर रहे हैं और उन्हें हल नहीं कर रहे हैं:

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

और फिर खुद ही ढेर देख रहा है। जैसा कि हम क्रोम प्रोफाइलिंग टूल में देख सकते हैं, यह 100 वादों को आवंटित करने के लिए आवश्यक मेमोरी को संचित करता है और फिर पूरे JSFIddle पृष्ठ के लिए 15 मेगाबाइट से कम पर "वहां रहता है"

यहां छवि विवरण दर्ज करें

दूसरी तरफ से अगर हम $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 के कुछ दिलचस्प पैटर्न भी देख सकते हैं यदि हम उनके अंतिम उदाहरण को कुछ और मिनटों तक चलने दें। हम देख सकते हैं कि इसमें कुछ समय लगता है - लेकिन यह कॉलबैक को साफ करने में सक्षम है।

यहां छवि विवरण दर्ज करें

संक्षेप में - कम से कम आधुनिक ब्राउज़रों में - आपको अनसुलझे वादों के बारे में चिंता करने की ज़रूरत नहीं है जब तक कि आपके पास उनके लिए बाहरी संदर्भ नहीं हैं


7
क्या इसका मतलब यह नहीं होगा कि अगर कोई वादा हल करने में बहुत लंबा समय लगता है (लेकिन अंततः हल हो जाएगा), तो यह GC'd होने का खतरा है?
w.brian

5
@ w.brian जब तक आप इसे कहीं भी असाइन नहीं करते हैं - उदाहरण के लिए एक चर के लिए: var b = $http.get(...)या इसमें कॉलबैक जोड़ें। वह भी इसका एक संदर्भ है। यदि कुछ इसे हल करता है (जैसे आपने कहा - अभी भी हल करने के लिए बहुत लंबा मतलब है समाधान) - इसके लिए इसका संदर्भ होना चाहिए। तो हाँ - यह GC'd नहीं होगा
बेंजामिन

3
समझे, यही मैंने सोचा था। तो, सवाल यह है कि "क्या कभी हल नहीं किए गए वादे स्मृति रिसाव का कारण बनते हैं?" आम उपयोग-मामले के लिए, जहां कॉलबैक वादे के लिए पारित किया जाता है, इसका उत्तर हां है। आपके उत्तर में यह पंक्ति विरोधाभासी प्रतीत होती है: "हम GC के कुछ दिलचस्प पैटर्न भी देख सकते हैं यदि हम उसके अंतिम उदाहरण को कुछ और मिनटों तक चलने दें। हम देख सकते हैं कि इसमें कुछ समय लगता है - लेकिन यह कॉलबैक को साफ करने में सक्षम है। " क्षमा करें, यदि मुझे पांडित्य और नाइट-पिकी हो रहा है, तो मैं केवल यह सुनिश्चित करने की कोशिश कर रहा हूं कि मैं इसे समझता हूं।
डब्ल्यू.ब्रायन

1
यह मेरे लिए समझ में नहीं आता है। अगर मैंने 100.000 वादे किए थे जो कंसोल.लॉग () एड कुछ लाइन। मैं चाहूंगा कि वे 100.000 उन पंक्तियों को लॉग करें यदि वे अचानक किसी जादू से हल करते हैं। या आप कह रहे हैं कि ब्राउज़र को पता चल जाएगा कि यह कभी भी हल नहीं होगा , क्योंकि न तो मेरे पास और न ही वास्तविक ब्राउज़र के पास इसका कोई संदर्भ है (कुछ भी इसे प्रभावित नहीं करता है) - तो यह कैसे सच हो सकता है? (हम्म, मैं देख सकता हूँ कि यह सच हो सकता है)
ओडिन्हो - वेलमॉन्ट १३'१६

8
इन टिप्पणियों में कुछ सच्चाई है और कुछ भ्रामक हैं, इसलिए मुझे स्पष्ट करना चाहिए: संलग्न हैंडलर के साथ एक वादा कचरा संग्रहण के लिए योग्य हो सकता है। एक वादा जिंदा रखा जाता है (जीसी-पात्र नहीं) यदि निम्न में से कोई भी सत्य है: (1) वादा वस्तु का एक संदर्भ है, (2) वादे की "स्थगित" स्थिति का संदर्भ है (वस्तु) / फ़ंक्शंस जो आप इसे हल करने / अस्वीकार करने के लिए उपयोग करते हैं)। इसके बाहर, वादा जीसी के लिए पात्र है। (अगर किसी के पास वादा नहीं है और कोई भी अपना राज्य नहीं बदल सकता है, तो इसका उद्देश्य अब और क्या है?)
cdhowie
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.