आधुनिक वेब विकास में, हम अक्सर घटनाओं से निपटते हैं, चाहे वह आने वाले वेबसॉकेट संदेशों, सर्वर-भेजे गए ईवेंट (एसएसई), या रेडिस पब/सब जैसी सेवाओं से डेटा स्ट्रीम को संभालना हो। जबकि Node.js ईवेंट-संचालित क्षमताएं प्रदान करता है, इसमें लूप्स के wait... का उपयोग करके ईवेंट पर एसिंक्रोनस रूप से पुनरावृति करने के लिए एक आउट-ऑफ़-द-बॉक्स तरीके का अभाव है।
इस पोस्ट में, मैं आपको टाइपस्क्रिप्ट और AsyncGenerator का उपयोग करके एक एसिंक्रोनस इवेंट इटरेटर बनाने का एक सरल लेकिन शक्तिशाली तरीका बताऊंगा। यह दृष्टिकोण आपको रद्दीकरण और सफाई तर्क पर पूर्ण नियंत्रण के साथ, स्वच्छ और पूर्वानुमानित तरीके से किसी भी प्रकार के ईवेंट एमिटर से ईवेंट का उपभोग करने की अनुमति देने के लिए डिज़ाइन किया गया है।
मेरे हाल के एक प्रोजेक्ट में, मुझे रेडिस पब/सब चैनलों को सुनने और सर्वर-भेजे गए इवेंट (एसएसई) को कनेक्टेड क्लाइंट्स को एसिंक्रोनस रूप से भेजने की जरूरत थी। चुनौती सिस्टम पर दबाव डाले बिना आने वाली घटनाओं को संभालने की थी, जबकि उपभोक्ता को किसी भी समय इवेंट स्ट्रीम को रद्द करने की अनुमति दी गई थी।
समाधान? एक ईवेंट इटरेटर जो किसी ईवेंट एमिटर (जैसे रेडिस पब/सब) को एक एसिंक्रोनस पुनरावर्तनीय में परिवर्तित करता है। यह हमें घटनाओं को नियंत्रित तरीके से संसाधित करने और आवश्यक होने पर रद्दीकरण को शालीनता से संभालने की अनुमति देता है।
आइए कार्यान्वयन के बारे में गहराई से जानें।
export type Context= { emit: (value: T) => void; cancel: () => void; }; export type CleanupFn = () => void | Promise ; export type Subscriber = ( context: Context , ) => void | CleanupFn | Promise ; export async function* createEventIterator ( subscriber: Subscriber , ): AsyncGenerator { const events: T[] = []; let cancelled = false; // Create a promise that resolves whenever a new event is added to the events array let resolveNext: (() => void) | null = null; const emit = (event: T) => { events.push(event); // If we are awaiting for a new event, resolve the promise if (resolveNext) { resolveNext(); resolveNext = null; } }; const cancel = () => { cancelled = true; }; const unsubscribe = await subscriber({ emit, cancel }); try { while (!cancelled) { // If there are events in the queue, yield the next event if (events.length > 0) { yield events.shift()!; } else { // Wait for the next event await new Promise ((resolve) => { resolveNext = resolve; }); } } // Process any remaining events that were emitted before cancellation. while (events.length > 0) { yield events.shift()!; } } finally { await unsubscribe?.(); } }
यह फ़ंक्शन एक सब्सक्राइबर फ़ंक्शन को स्वीकार करता है जिसे आप किसी भी इवेंट एमिटर या पब/सब सिस्टम से जोड़ सकते हैं। ग्राहक दो आवश्यक तरीके प्रदान करता है:
फ़ंक्शन एक AsyncGenerator
संदर्भ वस्तु:
Context
घटना कतार:
घटनाएँ: T[] सरणी उत्सर्जित घटनाओं को संग्रहीत करने के लिए एक बफर के रूप में कार्य करती है। जनरेटर इन घटनाओं को एक-एक करके संसाधित करेगा। यदि कतार में कोई ईवेंट नहीं है, तो यह अगले ईवेंट के उत्सर्जित होने की प्रतीक्षा करेगा।
तर्क उत्सर्जित करें:
एमिट फ़ंक्शन कतार में नए इवेंट जोड़ता है और किसी भी लंबित वादे को हल करता है (यानी, यदि जनरेटर नए इवेंट की प्रतीक्षा कर रहा है)।
रद्दीकरण:
यदि कैंसल फ़ंक्शन को कॉल किया जाता है, तो यह लूप से बाहर निकलने का संकेत देने के लिए एक ध्वज (रद्द = सत्य) सेट करता है। कतार में कोई भी शेष घटना जनरेटर के पूरा होने से पहले भी संसाधित की जाएगी।
साफ - सफाई:
रद्दीकरण के बाद, जनरेटर किसी भी आवश्यक सफ़ाई को करने के लिए अनसब्सक्राइब फ़ंक्शन (यदि प्रदान किया गया हो) को लागू करेगा। यह रेडिस जैसे बाहरी सिस्टम से सदस्यता समाप्त करने या संसाधनों की सफाई के लिए विशेष रूप से महत्वपूर्ण है।
आइए देखें कि हम रेडिस पब/सब को सुनने और आने वाले संदेशों पर एसिंक्रोनस रूप से पुनरावृति करने के लिए इस इवेंट इटरेटर का उपयोग कैसे कर सकते हैं।
import Redis from 'ioredis'; function redisEventIterator(channel: string) { const client = new Redis(); return createEventIterator(({ emit, cancel }) => { const messageHandler = (channel: string, message: string) => { emit(message); }; // Subscribe to the channel client.subscribe(channel); client.on('message', messageHandler); // Cleanup function to unsubscribe and disconnect return async () => { client.off('message', messageHandler); await client.unsubscribe(channel); await client.quit(); }; }); } // Usage (async () => { for await (const message of redisEventIterator('my-channel')) { console.log('New message:', message); // You can cancel the event stream if needed if (message === 'STOP') { break; } } })();
इस उदाहरण में, हम रेडिस पब/सब चैनल की सदस्यता लेने और संदेशों पर एसिंक्रोनस रूप से पुनरावृति करने के लिए createEventIterator का उपयोग करते हैं। हर बार जब कोई नया संदेश आता है, तो इसे जनरेटर में उत्सर्जित किया जाता है, जहां हम इसे वास्तविक समय में संसाधित कर सकते हैं। यदि कोई विशिष्ट संदेश (उदाहरण के लिए, "STOP") प्राप्त होता है, तो हम लूप तोड़ देते हैं और Redis से सदस्यता समाप्त कर देते हैं।
यहां बताया गया है कि आप Node.js के इवेंटएमिटर के साथ createEventIterator का उपयोग कैसे कर सकते हैं:
import { EventEmitter } from 'events'; function eventEmitterIterator(emitter: EventEmitter, eventName: string) { return createEventIterator(({ emit, cancel }) => { const eventHandler = (data: string) => emit(data); emitter.on(eventName, eventHandler); // Cleanup function to remove the listener return () => { emitter.off(eventName, eventHandler); }; }); } // Usage (async () => { const emitter = new EventEmitter(); // Simulate event emissions setTimeout(() => emitter.emit('data', 'First event'), 1000); setTimeout(() => emitter.emit('data', 'Second event'), 2000); setTimeout(() => emitter.emit('data', 'STOP'), 3000); for await (const event of eventEmitterIterator(emitter, 'data')) { console.log('Received event:', event); if (event === 'STOP') { break; } } })();
इस उदाहरण में:
अतुल्यकालिक नियंत्रण: AsyncGenerator का लाभ उठाकर, हम घटनाओं को अतुल्यकालिक रूप से संभाल सकते हैं, उन्हें अपनी गति से संसाधित कर सकते हैं, और जरूरत पड़ने पर प्रसंस्करण रोक सकते हैं।
रद्दीकरण: किसी भी समय ईवेंट स्ट्रीम को रद्द करने की क्षमता इस दृष्टिकोण को लचीला बनाती है, खासकर वास्तविक दुनिया के परिदृश्यों में जहां कनेक्शन को शालीनता से बंद करने की आवश्यकता हो सकती है।
सामान्य प्रयोजन: इस इटरेटर का उपयोग किसी भी ईवेंट एमिटर या पब/सब सिस्टम के लिए किया जा सकता है, जो इसे विभिन्न अनुप्रयोगों के लिए बहुमुखी बनाता है।
इवेंट-संचालित आर्किटेक्चर कई आधुनिक वेब अनुप्रयोगों की आधारशिला हैं, लेकिन जब हमें घटनाओं के प्रवाह को अतुल्यकालिक रूप से नियंत्रित करने की आवश्यकता होती है तो उन्हें प्रबंधित करना मुश्किल हो सकता है। टाइपस्क्रिप्ट में AsyncGenerator की शक्ति के साथ, आप इस इवेंट इटरेटर जैसे शानदार समाधान बना सकते हैं, जिससे आपका इवेंट-हैंडलिंग कोड साफ-सुथरा और बनाए रखना आसान हो जाएगा।
मुझे उम्मीद है कि यह पोस्ट आपको अपने स्वयं के इवेंट एमिटर्स के लिए एसिंक इटरेटर्स के साथ शुरुआत करने में मदद करेगी। यदि आपके कोई प्रश्न या विचार हैं, तो बेझिझक उन्हें टिप्पणियों में साझा करें!
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3