"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > Async जेनरेटर के साथ टाइपस्क्रिप्ट में इवेंट एमिटर्स पर एसिंक्रोनसली इटरेटिंग

Async जेनरेटर के साथ टाइपस्क्रिप्ट में इवेंट एमिटर्स पर एसिंक्रोनसली इटरेटिंग

2024-11-08 को प्रकाशित
ब्राउज़ करें:441

Asynchronously Iterating Over Event Emitters in TypeScript with Async Generators

परिचय

आधुनिक वेब विकास में, हम अक्सर घटनाओं से निपटते हैं, चाहे वह आने वाले वेबसॉकेट संदेशों, सर्वर-भेजे गए ईवेंट (एसएसई), या रेडिस पब/सब जैसी सेवाओं से डेटा स्ट्रीम को संभालना हो। जबकि 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?.();
    }
}

यह काम किस प्रकार करता है

यह फ़ंक्शन एक सब्सक्राइबर फ़ंक्शन को स्वीकार करता है जिसे आप किसी भी इवेंट एमिटर या पब/सब सिस्टम से जोड़ सकते हैं। ग्राहक दो आवश्यक तरीके प्रदान करता है:

  1. emit: सब्सक्राइबर को नए इवेंट को इटरेटर में पुश करने की अनुमति देता है।
  2. रद्द करें: यह संकेत देने का एक तरीका प्रदान करता है कि पुनरावृत्ति बंद होनी चाहिए।

फ़ंक्शन एक AsyncGenerator लौटाता है, जो आपको for waiting...of लूप का उपयोग करके घटनाओं पर पुनरावृत्ति करने की अनुमति देता है।

कोड को तोड़ना

  1. संदर्भ वस्तु:
    Context प्रकार नई घटनाओं को उत्सर्जित करने या सदस्यता रद्द करने के लिए एक इंटरफ़ेस प्रदान करता है। घटनाओं के प्रवाह को नियंत्रित करने के लिए ग्राहक इस संदर्भ का उपयोग करता है।

  2. घटना कतार:
    घटनाएँ: T[] सरणी उत्सर्जित घटनाओं को संग्रहीत करने के लिए एक बफर के रूप में कार्य करती है। जनरेटर इन घटनाओं को एक-एक करके संसाधित करेगा। यदि कतार में कोई ईवेंट नहीं है, तो यह अगले ईवेंट के उत्सर्जित होने की प्रतीक्षा करेगा।

  3. तर्क उत्सर्जित करें:
    एमिट फ़ंक्शन कतार में नए इवेंट जोड़ता है और किसी भी लंबित वादे को हल करता है (यानी, यदि जनरेटर नए इवेंट की प्रतीक्षा कर रहा है)।

  4. रद्दीकरण:
    यदि कैंसल फ़ंक्शन को कॉल किया जाता है, तो यह लूप से बाहर निकलने का संकेत देने के लिए एक ध्वज (रद्द = सत्य) सेट करता है। कतार में कोई भी शेष घटना जनरेटर के पूरा होने से पहले भी संसाधित की जाएगी।

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

उदाहरण: रेडिस पब/सब को सुनना

आइए देखें कि हम रेडिस पब/सब को सुनने और आने वाले संदेशों पर एसिंक्रोनस रूप से पुनरावृति करने के लिए इस इवेंट इटरेटर का उपयोग कैसे कर सकते हैं।

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;
        }
    }
})();

इस उदाहरण में:

  • हम ईवेंट उत्सर्जित करने के लिए इवेंटएमिटर का उपयोग करते हैं, जिन्हें createEventIterator द्वारा कैप्चर किया जाता है।
  • पुनरावर्तक 'डेटा' घटना को सुनता है और इसे अतुल्यकालिक रूप से संसाधित करता है।
  • रेडिस उदाहरण के समान, जब कोई विशिष्ट घटना ('STOP') प्राप्त होती है तो हम पुनरावृत्ति को रोक सकते हैं।

इस दृष्टिकोण के लाभ

  • अतुल्यकालिक नियंत्रण: AsyncGenerator का लाभ उठाकर, हम घटनाओं को अतुल्यकालिक रूप से संभाल सकते हैं, उन्हें अपनी गति से संसाधित कर सकते हैं, और जरूरत पड़ने पर प्रसंस्करण रोक सकते हैं।

  • रद्दीकरण: किसी भी समय ईवेंट स्ट्रीम को रद्द करने की क्षमता इस दृष्टिकोण को लचीला बनाती है, खासकर वास्तविक दुनिया के परिदृश्यों में जहां कनेक्शन को शालीनता से बंद करने की आवश्यकता हो सकती है।

  • सामान्य प्रयोजन: इस इटरेटर का उपयोग किसी भी ईवेंट एमिटर या पब/सब सिस्टम के लिए किया जा सकता है, जो इसे विभिन्न अनुप्रयोगों के लिए बहुमुखी बनाता है।

निष्कर्ष

इवेंट-संचालित आर्किटेक्चर कई आधुनिक वेब अनुप्रयोगों की आधारशिला हैं, लेकिन जब हमें घटनाओं के प्रवाह को अतुल्यकालिक रूप से नियंत्रित करने की आवश्यकता होती है तो उन्हें प्रबंधित करना मुश्किल हो सकता है। टाइपस्क्रिप्ट में AsyncGenerator की शक्ति के साथ, आप इस इवेंट इटरेटर जैसे शानदार समाधान बना सकते हैं, जिससे आपका इवेंट-हैंडलिंग कोड साफ-सुथरा और बनाए रखना आसान हो जाएगा।

मुझे उम्मीद है कि यह पोस्ट आपको अपने स्वयं के इवेंट एमिटर्स के लिए एसिंक इटरेटर्स के साथ शुरुआत करने में मदद करेगी। यदि आपके कोई प्रश्न या विचार हैं, तो बेझिझक उन्हें टिप्पणियों में साझा करें!

विज्ञप्ति वक्तव्य यह लेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/redjohnsh/asynchronous-iteating-over-event-emitters-in-typescript-with-async-generator-3mk?1 यदि कोई उल्लंघन है, तो कृपया स्टडी_गोलंग@163 से संपर्क करें इसे हटाने के लिए .com
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3