Fabrício का जवाब हाजिर है; लेकिन मैं कुछ कम तकनीकी के साथ उनके जवाब को पूरक करना चाहता था, जो कि एसिंक्रोनसिटी की अवधारणा को समझाने में मदद करने के लिए एक समानता पर ध्यान केंद्रित करता है ।
एक सादृश्य ...
कल, मैं जो काम कर रहा था वह एक सहयोगी से कुछ जानकारी के लिए आवश्यक था। मैंने उसे ऊपर उठाया; यहाँ बातचीत कैसे हुई:
मेरे : हाय बॉब, मुझे पता है कि कैसे हम जरूरत foo 'घ बार ' पिछले सप्ताह d। जिम इस पर एक रिपोर्ट चाहते हैं, और आप केवल एक ही हैं जो इसके बारे में विवरण जानते हैं।
बॉब : ज़रूर बात है, लेकिन मुझे लगभग 30 मिनट लगेंगे?
मैं : यह बहुत अच्छा है बॉब। जब आपको जानकारी मिली हो तो मुझे एक अंगूठी वापस दें!
इस बिंदु पर, मैंने फोन को लटका दिया। चूंकि मुझे अपनी रिपोर्ट पूरी करने के लिए बॉब से जानकारी की आवश्यकता थी, इसलिए मैंने रिपोर्ट छोड़ दी और इसके बजाय कॉफी के लिए चला गया, फिर मैंने कुछ ईमेल पर पकड़ा। 40 मिनट बाद (बॉब धीमा है), बॉब ने वापस बुलाया और मुझे वह जानकारी दी जिसकी मुझे ज़रूरत थी। इस बिंदु पर, मैंने अपनी रिपोर्ट के साथ अपना काम फिर से शुरू कर दिया, क्योंकि मेरे पास सभी आवश्यक जानकारी थी।
कल्पना करें कि क्या बातचीत इसके बजाय इस तरह से चली गई थी;
मेरे : हाय बॉब, मुझे पता है कि कैसे हम जरूरत foo 'घ बार ' पिछले सप्ताह d। जिम इस पर एक रिपोर्ट चाहते हैं, और आप केवल एक ही हैं जो इसके बारे में विवरण जानते हैं।
बॉब : ज़रूर बात है, लेकिन मुझे लगभग 30 मिनट लगेंगे?
मैं : यह बहुत अच्छा है बॉब। मैं इंतजार करूँगा।
और मैं वहीं बैठ कर इंतजार करने लगा। और इंतजार किया। और इंतजार किया। 40 मिनट के लिए। इंतजार के सिवा कुछ नहीं। आखिरकार, बॉब ने मुझे जानकारी दी, हमने हंगामा किया और मैंने अपनी रिपोर्ट पूरी की। लेकिन मैं उत्पादकता के 40 मिनट खो दिया है।
यह एसिंक्रोनस बनाम तुल्यकालिक व्यवहार है
यह वही है जो हमारे प्रश्न में सभी उदाहरणों में हो रहा है। एक छवि लोड हो रहा है, डिस्क से एक फ़ाइल लोड हो रहा है, और AJAX के माध्यम से एक पृष्ठ का अनुरोध सभी धीमी गति से संचालन कर रहे हैं (आधुनिक कंप्यूटिंग के संदर्भ में)।
इन धीमे संचालन के पूरा होने की प्रतीक्षा करने के बजाय , जावास्क्रिप्ट आपको एक कॉलबैक फ़ंक्शन को पंजीकृत करने की अनुमति देता है जो कि धीमी कार्रवाई पूरी होने पर निष्पादित किया जाएगा। हालांकि, इस बीच, जावास्क्रिप्ट अन्य कोड निष्पादित करना जारी रखेगा। तथ्य यह है कि जावास्क्रिप्ट धीमी गति से ऑपरेशन के पूरा होने के इंतजार में अन्य कोड निष्पादित करता है व्यवहार को अतुल्यकालिक बनाता है । यदि जावास्क्रिप्ट किसी अन्य कोड को निष्पादित करने से पहले ऑपरेशन के पूरा होने का इंतजार करता, तो यह समकालिक व्यवहार होता।
var outerScopeVar;
var img = document.createElement('img');
// Here we register the callback function.
img.onload = function() {
// Code within this function will be executed once the image has loaded.
outerScopeVar = this.width;
};
// But, while the image is loading, JavaScript continues executing, and
// processes the following lines of JavaScript.
img.src = 'lolcat.png';
alert(outerScopeVar);
उपरोक्त कोड में, हम जावास्क्रिप्ट को लोड करने के लिए कह रहे हैं lolcat.png
, जो एक स्लो ऑपरेशन है। इस धीमे संचालन के बाद कॉलबैक फ़ंक्शन निष्पादित किया जाएगा, लेकिन इस बीच, जावास्क्रिप्ट कोड की अगली पंक्तियों को संसाधित करता रहेगा; यानी alert(outerScopeVar)
।
यही कारण है कि हम सतर्क दिखाते हैं undefined
; चूंकि alert()
छवि को लोड किए जाने के बजाय तुरंत संसाधित किया जाता है।
अपने कोड को ठीक करने के लिए, हमें केवल कॉलबैक फ़ंक्शन मेंalert(outerScopeVar)
कोड को स्थानांतरित करना होगा । इसके परिणामस्वरूप, हमें अब outerScopeVar
वैरिएबल के रूप में घोषित किए गए वैरिएबल की आवश्यकता नहीं है ।
var img = document.createElement('img');
img.onload = function() {
var localScopeVar = this.width;
alert(localScopeVar);
};
img.src = 'lolcat.png';
आप हमेशा देखेंगे कि एक कॉलबैक एक फ़ंक्शन के रूप में निर्दिष्ट है, क्योंकि कुछ कोड को परिभाषित करने के लिए जावास्क्रिप्ट में एकमात्र * तरीका है, लेकिन बाद तक इसे निष्पादित नहीं करें।
इसलिए, हमारे सभी उदाहरणों में, function() { /* Do something */ }
कॉलबैक है; सभी उदाहरणों को ठीक करने के लिए, हमें केवल उस कोड को स्थानांतरित करना होगा जिसमें ऑपरेशन की प्रतिक्रिया की आवश्यकता है!
* तकनीकी रूप से आप इसका उपयोग कर सकते हैं eval()
, लेकिन इस उद्देश्य के लिए eval()
बुराई है
मैं अपने कॉलर को प्रतीक्षा में कैसे रखूं?
वर्तमान में आपके पास इसके समान कुछ कोड हो सकते हैं;
function getWidthOfImage(src) {
var outerScopeVar;
var img = document.createElement('img');
img.onload = function() {
outerScopeVar = this.width;
};
img.src = src;
return outerScopeVar;
}
var width = getWidthOfImage('lolcat.png');
alert(width);
हालांकि, अब हम जानते हैं कि return outerScopeVar
तुरंत होता है; onload
कॉलबैक फ़ंक्शन से पहले चर को अद्यतन किया गया है। यह getWidthOfImage()
वापस लौटने undefined
और undefined
सतर्क रहने की ओर जाता है ।
इसे ठीक करने के लिए, हमें getWidthOfImage()
कॉलबैक को पंजीकृत करने के लिए फ़ंक्शन को कॉल करने की अनुमति देने की आवश्यकता है , फिर उस कॉलबैक के भीतर होने वाली चौड़ाई के एलर्टिंग को स्थानांतरित करें;
function getWidthOfImage(src, cb) {
var img = document.createElement('img');
img.onload = function() {
cb(this.width);
};
img.src = src;
}
getWidthOfImage('lolcat.png', function (width) {
alert(width);
});
... पहले की तरह, ध्यान दें कि हम वैश्विक चर (इस मामले में width
) निकालने में सक्षम हैं ।