इवेंट लूप को समझना


135

मैं इसके बारे में सोच रहा हूं और यही मैं इसके साथ आया हूं:

आइए इस कोड को नीचे देखें:

console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);

एक अनुरोध आता है, और जेएस इंजन कदम से कदम ऊपर कोड निष्पादित करना शुरू कर देता है। पहले दो कॉल सिंक कॉल हैं। लेकिन जब यह setTimeoutविधि की बात आती है , तो यह एक async निष्पादन बन जाता है। लेकिन जेएस तुरंत इससे लौटता है और निष्पादित करना जारी रखता है, जिसे कहा जाता है Non-Blockingया Async। और यह अन्य आदि पर काम करना जारी रखता है।

इस निष्पादन के परिणाम निम्नलिखित हैं:

acdb

तो मूल रूप से दूसरा setTimeoutपहले समाप्त हो गया और इसके कॉलबैक फ़ंक्शन को पहले वाले की तुलना में पहले निष्पादित किया गया और इससे समझ में आता है।

हम यहां सिंगल-थ्रेडेड एप्लिकेशन के बारे में बात कर रहे हैं। जेएस इंजन इसे निष्पादित करता रहता है और जब तक यह पहला अनुरोध पूरा नहीं करता है, यह दूसरे पर नहीं जाएगा। लेकिन अच्छी बात यह है कि यह ब्लॉकिंग ऑपरेशंस के लिए इंतजार नहीं करेगा जैसे कि इसे setTimeoutहल करने के लिए यह तेज़ होगा क्योंकि यह नए आने वाले अनुरोधों को स्वीकार करता है।

लेकिन मेरे सवाल निम्नलिखित मदों के आसपास उठते हैं:

# 1: अगर हम एकल-थ्रेडेड एप्लिकेशन के बारे में बात कर रहे हैं, तो setTimeoutsजेएस इंजन अधिक अनुरोधों को स्वीकार करते हुए और उन्हें निष्पादित करते हुए क्या प्रक्रिया करता है? एकल धागा अन्य अनुरोधों पर कैसे काम करना जारी रखता है? setTimeoutअन्य अनुरोधों के आने और क्रियान्वित होने पर क्या काम करता है ।

# 2: यदि इन setTimeoutअनुरोधों को पर्दे के पीछे निष्पादित किया जाता है, जबकि अधिक अनुरोध आ रहे हैं और निष्पादित किए जा रहे हैं, तो पर्दे के पीछे से एसिंक्स निष्पादित क्या करता है? यह कौन सी बात है जिस पर हम बात करते हैं EventLoop?

# 3: लेकिन क्या पूरे तरीके को EventLoopऐसा नहीं रखा जाना चाहिए जिससे कि पूरी चीज निष्पादित हो जाए और कॉलबैक विधि को कॉल किया जाए? कॉलबैक फ़ंक्शंस के बारे में बात करते समय यह मेरी समझ में आता है:

function downloadFile(filePath, callback)
{
   blah.downloadFile(filePath);
   callback();
}

लेकिन इस मामले में, जेएस इंजन को यह कैसे पता चलता है कि क्या यह एक एसिंक्स फ़ंक्शन है ताकि यह कॉलबैक को अंदर रख सके EventLoop? शायद asyncC # में कीवर्ड की तरह कुछ या किसी प्रकार की विशेषता जो जेएस इंजन को लेने वाली विधि को इंगित करती है एक एसिंक्स विधि है और उसके अनुसार इलाज किया जाना चाहिए।

# 4: लेकिन एक लेख कहता है कि जो चीजें काम कर रही थीं, मैं उस पर काफी विपरीत था:

इवेंट लूप कॉलबैक फ़ंक्शन की एक कतार है। जब कोई async फ़ंक्शन निष्पादित होता है, तो कॉलबैक फ़ंक्शन को कतार में धकेल दिया जाता है। जावास्क्रिप्ट इंजन ईवेंट लूप को तब तक संसाधित करना शुरू नहीं करता है जब तक कि किसी async फ़ंक्शन द्वारा कोड को निष्पादित नहीं किया जाता है।

# 5: और यहाँ यह छवि है जो सहायक हो सकती है लेकिन छवि में पहली व्याख्या यह कह रही है कि प्रश्न संख्या 4 में उल्लिखित एक ही बात है:

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

तो मेरा प्रश्न यहाँ ऊपर सूचीबद्ध वस्तुओं के बारे में कुछ स्पष्टीकरण प्राप्त करना है?


1
उन समस्याओं को संभालने के लिए थ्रेड्स सही रूपक नहीं हैं। घटनाओं पर विचार करें।
डेनिज सेगुरेट

1
@ डिस्ट्रॉय: जेएस में उस घटना के रूपक को दर्शाने के लिए एक कोड नमूना देखने में अच्छा लगेगा।
तारिक

मैं यह नहीं देखता कि यहाँ आपका सवाल क्या है।
डेनिस सेगुरेट

1
@ डायस्ट्रो: मेरा प्रश्न यहाँ ऊपर सूचीबद्ध वस्तुओं के बारे में कुछ स्पष्टीकरण प्राप्त करना है?
तारिक

2
नोड एकल थ्रेडेड नहीं है, लेकिन यह आपके लिए कोई मायने नहीं रखता है (इस तथ्य के अलावा कि यह आपके उपयोगकर्ता कोड को निष्पादित करते समय अन्य चीजों को प्राप्त करने का प्रबंधन करता है)। आपके उपयोगकर्ता कोड में केवल एक कॉलबैक को एक समय में निष्पादित किया जाता है।
डेनस सेग्रुट

जवाबों:


85

1: यदि हम एकल-थ्रेडेड एप्लिकेशन के बारे में बात कर रहे हैं, तो जेएस इंजन अधिक अनुरोधों को स्वीकार करता है और उन्हें निष्पादित करता है, तो क्या प्रक्रियाएँ सेटटाइमआउट करती हैं? क्या वह एकल धागा अन्य अनुरोधों पर काम करना जारी रखेगा? फिर कौन सेटटाइमआउट पर काम करता रहता है जबकि अन्य अनुरोध आते रहते हैं और निष्पादित हो जाते हैं।

नोड प्रक्रिया में केवल 1 धागा है जो वास्तव में आपके प्रोग्राम के जावास्क्रिप्ट को निष्पादित करेगा। हालाँकि, नोड के भीतर, वास्तव में इवेंट लूप तंत्र के संचालन के कई थ्रेड्स हैं, और इसमें IO थ्रेड्स का एक पूल और कुछ मुट्ठी भर अन्य शामिल हैं। कुंजी यह है कि इन थ्रेड्स की संख्या समवर्ती कनेक्शनों की संख्या के अनुरूप नहीं है, जैसे कि वे एक थ्रेड-प्रति-कनेक्शन संगामिति मॉडल में होंगे।

अब "निष्पादित सेटटाइमआउट" के बारे में, जब आप आह्वान करते हैं setTimeout, तो सभी नोड मूल रूप से भविष्य में एक समय में निष्पादित होने वाले कार्यों की एक डेटा संरचना को अपडेट करते हैं। इसमें मूल रूप से सामान की कतारों का एक गुच्छा होता है, जिसे करने की आवश्यकता होती है और ईवेंट लूप के प्रत्येक "टिक" का चयन करता है, इसे कतार से हटाता है, और इसे चलाता है।

समझने के लिए एक महत्वपूर्ण बात यह है कि नोड अधिकांश भारी उठाने के लिए ओएस पर निर्भर करता है। इसलिए आने वाले नेटवर्क अनुरोधों को वास्तव में ओएस द्वारा ही ट्रैक किया जाता है और जब नोड एक को संभालने के लिए तैयार होता है, तो यह केवल एक सिस्टम कॉल का उपयोग करता है जिससे ओएस नेटवर्क से अनुरोध करने के लिए तैयार हो सके। इतना IO "काम" नोड या तो "हे ओएस, पढ़ने के लिए तैयार डेटा के साथ एक नेटवर्क कनेक्शन मिला है?" या "हे OS, मेरे किसी भी उत्कृष्ट फाइलसिस्टम कॉल में डेटा तैयार है?"। इसकी आंतरिक एल्गोरिथ्म और ईवेंट लूप इंजन डिज़ाइन के आधार पर, नोड जावास्क्रिप्ट के एक "टिक" का चयन करेगा, निष्पादित करने के लिए, इसे चलाएगा, फिर सभी प्रक्रिया को दोहराएगा। इवेंट लूप का यही मतलब है। नोड मूल रूप से हर समय यह निर्धारित करता है कि "जावास्क्रिप्ट का अगला छोटा हिस्सा मुझे क्या चलना चाहिए?", फिर इसे चलाएं।setTimeoutया process.nextTick

2: यदि इन सेटटाइमआउट को पर्दे के पीछे निष्पादित किया जाएगा, जबकि अधिक अनुरोध आ रहे हैं, और निष्पादित किए जा रहे हैं, तो बात पर्दे के पीछे के एसिंक्स निष्पादन को अंजाम देती है, जिस पर हम EventLoop के बारे में बात कर रहे हैं?

कोई भी जावास्क्रिप्ट पर्दे के पीछे नहीं जाता है। आपके कार्यक्रम के सभी जावास्क्रिप्ट एक समय में एक सामने और एक केंद्र में चलते हैं। पर्दे के पीछे क्या होता है OS हैंडल IO और नोड इंतजार करता है कि तैयार होने के लिए और नोड निष्पादन के लिए प्रतीक्षा कर रही जावास्क्रिप्ट की अपनी कतार का प्रबंधन करता है।

3: जेएस इंजन को कैसे पता चल सकता है कि क्या यह एक एसिंक्स फ़ंक्शन है ताकि इसे ईवेंटऑलॉप में डाल सकें?

नोड कोर में फ़ंक्शंस का एक निश्चित सेट है जो एसिंक्स्ट है क्योंकि वे सिस्टम कॉल करते हैं और नोड जानते हैं कि ये इसलिए हैं क्योंकि उन्हें ओएस या सी ++ कॉल करना है। मूल रूप से सभी नेटवर्क और फाइल सिस्टम IO के साथ-साथ चाइल्ड प्रोसेस इंटरैक्शन अतुल्यकालिक होगा और केवल उसी तरह से जावास्क्रिप्ट को नोड चलाने के लिए कुछ असिंक्रोनस तरीके से मिल सकता है, नोड कोर लाइब्रेरी द्वारा प्रदान किए गए async कार्यों में से एक को लागू करने से। यहां तक ​​कि अगर आप एक एनपीएम पैकेज का उपयोग कर रहे हैं, जो ईवेंट लूप का उत्पादन करने के लिए स्वयं एपीआई है, तो अंततः एनपीएम पैकेज का कोड नोड कोर के एसिंक्स फ़ंक्शन में से एक को कॉल करेगा और जब नोड जानता है कि टिक पूरा हो गया है और यह ईवेंट शुरू कर सकता है। लूप एल्गोरिदम फिर से।

4 इवेंट लूप कॉलबैक फ़ंक्शन की एक कतार है। जब कोई async फ़ंक्शन निष्पादित होता है, तो कॉलबैक फ़ंक्शन को कतार में धकेल दिया जाता है। जावास्क्रिप्ट इंजन ईवेंट लूप को तब तक संसाधित करना शुरू नहीं करता है जब तक कि किसी async फ़ंक्शन द्वारा कोड को निष्पादित नहीं किया जाता है।

हां, यह सच है, लेकिन यह भ्रामक है। मुख्य बात सामान्य पैटर्न है:

//Let's say this code is running in tick 1
fs.readFile("/home/barney/colors.txt", function (error, data) {
  //The code inside this callback function will absolutely NOT run in tick 1
  //It will run in some tick >= 2
});
//This code will absolutely also run in tick 1
//HOWEVER, typically there's not much else to do here,
//so at some point soon after queueing up some async IO, this tick
//will have nothing useful to do so it will just end because the IO result
//is necessary before anything useful can be done

तो हाँ, आप पूरी तरह से केवल एक ही टिक में सभी स्मृति में सभी समान रूप से फाइबोनैचि संख्याओं को गिनकर ईवेंट लूप को पूरी तरह से ब्लॉक कर सकते हैं, और हाँ जो आपके प्रोग्राम को पूरी तरह से फ्रीज कर देगा। यह सहकारिता की संगति है। जावास्क्रिप्ट के प्रत्येक टिक को कुछ उचित समय के भीतर या समग्र आर्किटेक्चर विफल होने पर इवेंट लूप का उत्पादन करना चाहिए।


1
कहते हैं कि मेरे पास एक कतार है जो सर्वर को निष्पादित करने में 1 मिनट का समय लेगी, और पहली बात यह थी कि कुछ async फ़ंक्शन है जो 10 सेकंड के बाद समाप्त हो जाता है। क्या यह कतार के अंत तक जाएगा या यह तैयार होने वाली लाइन में खुद को धकेल देगा?
ऑइलो

4
आम तौर पर यह कतार के अंत तक जाएगा, लेकिन process.nextTickबनाम setTimeoutबनाम के शब्दार्थ setImmediateसूक्ष्म रूप से भिन्न होते हैं, हालांकि आपको वास्तव में परवाह नहीं करनी चाहिए। मेरे पास एक ब्लॉग पोस्ट है जिसे सेटटाइमआउट कहा जाता है और जो मित्र अधिक विवरण में जाते हैं।
पीटर लियोन

क्या आप कृपया विस्तार से बता सकते हैं? हम कहते हैं कि मेरे पास दो कॉलबैक हैं और पहले वाले के पास 10mS के निष्पादन के समय के साथ एक बदलाव विधि है और 1 मिनट का सेटटाइमआउट है और दूसरे में 10 सेकंड के सेटटाइमआउट के साथ 50ms के निष्पादन समय के साथ एक बदलावबैक विधि है। मुझे लगता है कि परिवर्तन पहले से कतार में होगा और परिवर्तन अगला होगा। उसके बाद ईवेंट लूप समकालिक तरीके से चुनता है। क्या मैं सही हू?
शीशपई

1
@ शीशपई यह सबको भ्रमित करने के लिए कोड पर चर्चा करने के लिए जब अंग्रेजी के पैराग्राफ में लिखा है। कोड स्निपेट के साथ बस एक नया प्रश्न पोस्ट करें ताकि लोग कोड के विवरण के बजाय कोड के आधार पर उत्तर दे सकें, जो बहुत अधिक अस्पष्टता छोड़ देता है।
पीटर लियोंस

youtube.com/watch?v=QyUFheng6J0&spfreload=5 यह जावास्क्रिप्ट इंजन की एक और अच्छी व्याख्या है
मुकेश कुमार

65

फिलिप रॉबर्ट्स द्वारा एक शानदार वीडियो ट्यूटोरियल है, जो जावास्क्रिप्ट इवेंट लूप को सबसे सरल और वैचारिक तरीके से समझाता है। हर जावास्क्रिप्ट डेवलपर पर एक नज़र होनी चाहिए।

यहाँ Youtube पर वीडियो लिंक दिया गया है।


16
मैंने इसे देखा और यह वास्तव में अब तक का सबसे अच्छा स्पष्टीकरण था।
तारिक

1
जावास्क्रिप्ट प्रशंसकों और उत्साही लोगों के लिए वीडियो देखना चाहिए।
वायरस जूल

1
इस वीडियो ने मेरे लाइव को ^ ^
HuTTran

1
यहाँ भटकते हुए आया .. और यह मुझे मिली सबसे अच्छी व्याख्या में से एक है .. साझा करने के लिए धन्यवाद ...: D
रोहित

1
वह एक
चश्मदीद

11

लगता है कि मेजबान प्रक्रिया को एकल-थ्रेडेड नहीं किया जा सकता है, वे नहीं हैं। एकल-थ्रेडेड क्या होस्ट प्रक्रिया का हिस्सा है जो आपके जावास्क्रिप्ट कोड को निष्पादित करता है।

पृष्ठभूमि के श्रमिकों को छोड़कर , लेकिन ये परिदृश्य को जटिल बनाते हैं ...

तो, आपके सभी js कोड एक ही थ्रेड में चलते हैं, और इस बात की कोई संभावना नहीं है कि आपको अपने js कोड के दो अलग-अलग भाग समवर्ती रूप से चलाने के लिए मिलते हैं (इसलिए, आपको मैनेज करने के लिए concurrency nigthmare नहीं मिलती है)।

जेएस कोड जो निष्पादित कर रहा है वह अंतिम कोड है जिसे होस्ट प्रक्रिया ने इवेंट लूप से उठाया है। अपने कोड में आप मूल रूप से दो काम कर सकते हैं: सिंक्रोनस निर्देश चलाएँ, और कुछ घटनाओं के होने पर भविष्य में निष्पादित करने के लिए शेड्यूल फ़ंक्शन करें।

यहाँ मेरा मानसिक प्रतिनिधित्व है (सावधान रहें: यह सिर्फ इतना है, मुझे आपके उदाहरण कोड के ब्राउज़र कार्यान्वयन विवरण नहीं पता हैं):

console.clear();                                   //exec sync
console.log("a");                                  //exec sync
setTimeout(                //schedule inAWhile to be executed at now +1 s 
    function inAWhile(){
        console.log("b");
    },1000);    
console.log("c");                                  //exec sync
setTimeout(
    function justNow(){          //schedule justNow to be executed just now
        console.log("d");
},0);       

जब आपका कोड चल रहा होता है, तो होस्ट प्रक्रिया में एक और थ्रेड उन सभी सिस्टम इवेंट्स पर नज़र रखता है, जो घटित हो रहे हैं (UI पर क्लिक, फ़ाइलें पढ़ें, नेटवर्क पैकेट प्राप्त आदि)

जब आपका कोड पूरा हो जाता है, तो इसे इवेंट लूप से हटा दिया जाता है, और होस्ट प्रक्रिया इसे चेक करने के लिए वापस आती है, यह देखने के लिए कि क्या चलाने के लिए अधिक कोड हैं। ईवेंट लूप में दो ईवेंट हैंडलर अधिक होते हैं: एक को अब निष्पादित किया जाना (जस्टनॉ फंक्शन), और दूसरा एक सेकंड (इनॉवेल फंक्शन) के भीतर।

मेजबान प्रक्रिया अब सभी घटनाओं से मिलान करने की कोशिश करती है, यह देखने के लिए कि क्या हैंडलर ने उनके लिए पंजीकरण किया है। यह पाया गया कि जिस घटना का अभी-अभी इंतजार हो रहा है, वह हो गई है, इसलिए वह अपना कोड चलाना शुरू कर देती है। जब जस्ट फंक्शन निकलता है, तो यह इवेंट लूप की दूसरी बार जांच करता है, घटनाओं पर हैंडलर के लिए खोज करना। यह मानकर कि 1 s बीत चुका है, यह inAWhile फ़ंक्शन को चलाता है, और इसी तरह…।


सेटटाइमआउट को मुख्य थ्रेड में लागू किया जाता है, हालांकि। इसलिए आपके उदाहरण में ऐसा कुछ नहीं है जिसके लिए अलग थ्रेड की आवश्यकता हो। वास्तव में, ब्राउज़रों में केवल टैब को कई थ्रेड्स में लागू किया जाता है। एक ही टैब में, एकाधिक समानांतर नेटवर्क कनेक्शन बनाने माउस क्लिक के लिए इंतज़ार कर, setTimeout, एनिमेशन आदि सहित सभी प्रक्रियाओं एक ही धागे में किया जाता
slebetman
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.