एक घटना एक अधिसूचना है जो हाल के समय से एक घटना का वर्णन करती है।
इवेंट-संचालित सिस्टम का एक विशिष्ट कार्यान्वयन एक इवेंट डिस्पैचर और हैंडलर फ़ंक्शन (या सब्सक्राइबर ) का उपयोग करता है। डिस्पैचर घटनाओं (jQuery के bind), और अपने ग्राहकों triggerको jQuery में एक घटना प्रकाशित करने के लिए एक विधि के लिए तार संचालकों के लिए एक एपीआई प्रदान करता है । जब आप IO या UI घटनाओं के बारे में बात कर रहे हैं, तो आमतौर पर एक इवेंट लूप भी होता है , जो माउस-क्लिक जैसी नई घटनाओं का पता लगाता है और उन्हें डिस्पैचर में भेजता है। जेएस-भूमि में, डिस्पैचर और इवेंट लूप ब्राउज़र द्वारा प्रदान किए जाते हैं।
कोड के लिए जो उपयोगकर्ता के साथ सीधे इंटरैक्ट करता है - कीपेस और क्लिक्स का जवाब देना - ईवेंट-चालित प्रोग्रामिंग (या इसके प्रकार, जैसे कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग ) लगभग अपरिहार्य है। आप, प्रोग्रामर, को पता नहीं है कि उपयोगकर्ता कब या कहाँ क्लिक करने जा रहा है, इसलिए यह अपने इवेंट लूप में उपयोगकर्ता की कार्रवाई का पता लगाने और अपने कोड को सूचित करने के लिए GUI फ्रेमवर्क या ब्राउज़र के नीचे है। इस प्रकार की अवसंरचना का उपयोग नेटवर्किंग अनुप्रयोगों (cf NodeJS) में भी किया जाता है।
आपका उदाहरण, जिसमें आप किसी फ़ंक्शन को सीधे कॉल करने के बजाय अपने कोड में एक घटना बढ़ाते हैं, कुछ और दिलचस्प ट्रेडऑफ़ हैं, जिनकी मैं नीचे चर्चा करूंगा। मुख्य अंतर यह है कि किसी घटना के प्रकाशक ( makeItSnow) कॉल के रिसीवर को निर्दिष्ट नहीं करता है; वह कहीं और तार दिया गया है ( bindआपके उदाहरण में कॉल में)। इसे अग्नि-विस्मरण कहा जाता है : यह makeItSnowघोषणा करता है कि दुनिया में बर्फबारी हो रही है, लेकिन यह परवाह नहीं करता है कि कौन क्या सुन रहा है, आगे क्या होता है, या जब ऐसा होता है - यह बस संदेश प्रसारित करता है और अपने हाथों से धूल जाता है।
तो घटना-संचालित दृष्टिकोण रिसीवर से संदेश के प्रेषक को डिकॉउंड करता है। इससे एक फायदा यह होता है कि आप दिए गए इवेंट में कई हैंडलर लगा सकते हैं। gritRoadsमौजूदा shovelSnowहैंडलर को प्रभावित किए बिना आप अपने स्नो इवेंट में एक समारोह में शामिल हो सकते हैं । आपके आवेदन के वायर्ड होने के तरीके में आपके पास लचीलापन है; एक व्यवहार को बंद करने के लिए आपको bindकोड को व्यवहार के सभी उदाहरणों को खोजने के लिए कोड के माध्यम से जाने के बजाय कॉल को हटाने की आवश्यकता है ।
ईवेंट-चालित प्रोग्रामिंग का एक और लाभ यह है कि यह आपको कहीं-कहीं क्रॉस-कटिंग चिंताओं को दूर करने के लिए देता है। ईवेंट डिस्पैचर मध्यस्थ की भूमिका निभाता है , और कुछ पुस्तकालय (जैसे ब्राइटर ) एक पाइपलाइन का उपयोग करते हैं ताकि आप लॉगिंग या गुणवत्ता-सेवा जैसी आसानी से सामान्य आवश्यकताओं को प्लग-इन कर सकें।
पूर्ण प्रकटीकरण: ब्रिडल को हडले में विकसित किया गया है, जहां मैं काम करता हूं।
रिसीवर से एक घटना के प्रेषक को डिकूप करने का तीसरा लाभ यह है कि जब आप घटना को संभालते हैं तो यह आपको लचीलापन देता है । आप प्रत्येक प्रकार के ईवेंट को अपने स्वयं के थ्रेड पर संसाधित कर सकते हैं (यदि आपका ईवेंट डिस्पैचर इसका समर्थन करता है), या आप रैबिटएमक्यू जैसे संदेश ब्रोकर पर उठाए गए ईवेंट डाल सकते हैं और उन्हें एक एसिंक्रोनस प्रक्रिया के साथ संभाल सकते हैं या रात भर में उन्हें संसाधित कर सकते हैं। घटना का रिसीवर एक अलग प्रक्रिया में या एक अलग मशीन पर हो सकता है। आपको कोड बदलने की ज़रूरत नहीं है जो ऐसा करने के लिए घटना को उठाता है! यह "microservice" आर्किटेक्चर के पीछे बड़ा आइडिया है: ऑटोनोमस सेवाएं ईवेंट का उपयोग करके संचार करती हैं, साथ ही संदेशवाहक को एप्लिकेशन की रीढ़ के रूप में संदेश देती हैं।
ईवेंट-चालित शैली के एक अलग रूप से भिन्न उदाहरण के लिए, डोमेन-संचालित डिज़ाइन को देखें, जहाँ एग्रीगेट को अलग रखने में सहायता के लिए डोमेन ईवेंट का उपयोग किया जाता है। उदाहरण के लिए, एक ऑनलाइन स्टोर पर विचार करें जो आपके खरीद इतिहास के आधार पर उत्पादों की सिफारिश करता है। एक Customerअपनी खरीद इतिहास को अद्यतन किया है जब एक की जरूरत ShoppingCartके लिए भुगतान किया जाता है। ShoppingCartकुल सूचित कर सकते हैं Customerएक बढ़ाकर CheckoutCompletedघटना; Customerघटना के जवाब में एक अलग लेन-देन में अपडेट कर दिया जाएगा।
इस घटना-संचालित मॉडल का मुख्य पहलू अप्रत्यक्ष है। अब उस कोड को ढूंढना कठिन है जो ईवेंट को संभालता है क्योंकि आप अपने आईडीई का उपयोग करके इसे नेविगेट नहीं कर सकते हैं; आपको यह पता लगाना होगा कि घटना कॉन्फ़िगरेशन में कहां है और आशा है कि आपको सभी हैंडलर मिल गए हैं। आपके सिर में किसी भी समय रखने के लिए अधिक सामान है। कोड स्टाइल कन्वेंशन यहां मदद कर सकते हैं (उदाहरण के लिए, सभी कॉल को bindएक फ़ाइल में रखना)। अपनी पवित्रता के लिए, केवल एक ईवेंट डिस्पैचर का उपयोग करना और उसे लगातार उपयोग करना महत्वपूर्ण है।
एक और नुकसान यह है कि घटनाओं को फिर से भरना मुश्किल है। यदि आपको किसी घटना के प्रारूप को बदलने की आवश्यकता है तो आपको सभी रिसीवरों को भी बदलना होगा। यह तब समाप्त हो जाता है जब किसी ईवेंट के ग्राहक विभिन्न मशीनों पर होते हैं, क्योंकि अब आपको सॉफ़्टवेयर रिलीज़ को सिंक्रनाइज़ करने की आवश्यकता है!
कुछ परिस्थितियों में, प्रदर्शन एक चिंता का विषय हो सकता है। संदेश को संसाधित करते समय, डिस्पैचर को निम्न करना होता है:
- कुछ डेटा संरचना में सही हैंडलर देखें।
- प्रत्येक हैंडलर के लिए एक संदेश प्रसंस्करण पाइपलाइन बनाएँ। इसमें मेमोरी आवंटन का एक समूह शामिल हो सकता है।
- गतिशील रूप से हैंडलर को बुलाओ (संभवत: प्रतिबिंब का उपयोग करते हुए अगर भाषा को इसकी आवश्यकता है)।
यह निश्चित रूप से एक नियमित फ़ंक्शन कॉल की तुलना में धीमा है, जिसमें केवल स्टैक पर एक नया फ्रेम पुश करना शामिल है। हालाँकि, लचीलापन जो एक ईवेंट-चालित आर्किटेक्चर आपको पसंद करता है, धीमी कोड को अलग करना और अनुकूलित करना बहुत आसान बनाता है। एक अतुल्यकालिक प्रोसेसर के लिए काम प्रस्तुत करने की क्षमता होने के नाते यहां एक बड़ी जीत है, क्योंकि यह आपको तुरंत अनुरोध करने की अनुमति देता है जबकि पृष्ठभूमि में कड़ी मेहनत से निपटा जाता है। किसी भी स्थिति में, यदि आप स्क्रीन पर DB या ड्राइंग सामान के साथ बातचीत कर रहे हैं, तो IO की लागत किसी संदेश को संसाधित करने की लागतों को पूरी तरह से स्वाहा कर देगी। यह समय से पहले अनुकूलन से बचने का मामला है।
संक्षेप में, घटनाओं में शिथिल युग्मित सॉफ़्टवेयर बनाने का एक शानदार तरीका है, लेकिन वे लागत के बिना नहीं हैं। उदाहरण के लिए, यह गलत होगा कि आपके एप्लिकेशन में प्रत्येक फ़ंक्शन कॉल को किसी ईवेंट के साथ बदल दिया जाए। सार्थक स्थापत्य विभाजन बनाने के लिए घटनाओं का उपयोग करें।
$(document).bind('snow', shovelShow)। किसी अनाम फ़ंक्शन में इसे लपेटने की आवश्यकता नहीं है।