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
) निकालने में सक्षम हैं ।