'for await...of' लूप और कस्टम एसिंक इटरेटर हेल्पर्स का उपयोग करके जावास्क्रिप्ट में एसिंक्रोनस इटरेशन में महारत हासिल करें। व्यावहारिक उदाहरणों के साथ स्ट्रीम प्रोसेसिंग और डेटा हैंडलिंग को बेहतर बनाएं।
जावास्क्रिप्ट एसिंक इटरेटर हेल्पर: फॉर ईच - स्ट्रीम प्रोसेसिंग इटरेशन
एसिंक्रोनस प्रोग्रामिंग आधुनिक जावास्क्रिप्ट विकास की एक आधारशिला है, जो एप्लिकेशन को मुख्य थ्रेड को ब्लॉक किए बिना समय लेने वाले ऑपरेशन को संभालने में सक्षम बनाती है। ECMAScript 2018 में पेश किए गए एसिंक इटरेटर, एसिंक्रोनस रूप से डेटा स्ट्रीम को प्रोसेस करने के लिए एक शक्तिशाली तंत्र प्रदान करते हैं। यह ब्लॉग पोस्ट एसिंक इटरेटर की अवधारणा पर गहराई से चर्चा करता है और स्ट्रीम प्रोसेसिंग को सुव्यवस्थित करने के लिए एक एसिंक्रोनस 'फॉर ईच' हेल्पर फ़ंक्शन को लागू करने का तरीका प्रदर्शित करता है।
एसिंक इटरेटर को समझना
एक एसिंक इटरेटर एक ऑब्जेक्ट है जो एसिंकइटरेटर इंटरफ़ेस का पालन करता है। यह एक next() मेथड को परिभाषित करता है जो एक प्रॉमिस लौटाता है, जो दो प्रॉपर्टी वाले ऑब्जेक्ट में रिज़ॉल्व होता है:
value: अनुक्रम में अगला मान।done: एक बूलियन जो इंगित करता है कि इटरेटर पूरा हो गया है या नहीं।
एसिंक इटरेटर का उपयोग आमतौर पर नेटवर्क स्ट्रीम, फाइल सिस्टम, या डेटाबेस जैसे एसिंक्रोनस स्रोतों से डेटा का उपभोग करने के लिए किया जाता है। for await...of लूप एसिंक इटरेबल्स पर इटरेट करने के लिए एक सुविधाजनक सिंटैक्स प्रदान करता है।
उदाहरण: किसी फ़ाइल से एसिंक्रोनस रूप से पढ़ना
एक ऐसे परिदृश्य पर विचार करें जहाँ आपको मुख्य थ्रेड को ब्लॉक किए बिना एक बड़ी फ़ाइल को लाइन दर लाइन पढ़ने की आवश्यकता है। आप इसे एक एसिंक इटरेटर का उपयोग करके प्राप्त कर सकते हैं:
const fs = require('fs');
const readline = require('readline');
async function* readFileLines(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
for await (const line of rl) {
yield line;
}
}
async function processFile(filePath) {
for await (const line of readFileLines(filePath)) {
console.log(`Line: ${line}`);
}
}
// Example usage
processFile('path/to/your/file.txt');
इस उदाहरण में, readFileLines एक एसिंक जेनरेटर फ़ंक्शन है जो फ़ाइल की प्रत्येक लाइन को पढ़े जाने पर उत्पन्न (yield) करता है। processFile फ़ंक्शन फिर for await...of का उपयोग करके लाइनों पर इटरेट करता है, प्रत्येक लाइन को एसिंक्रोनस रूप से प्रोसेस करता है।
एक एसिंक 'फॉर ईच' हेल्पर को लागू करना
हालांकि for await...of लूप उपयोगी है, लेकिन जब आपको स्ट्रीम में प्रत्येक तत्व पर जटिल ऑपरेशन करने की आवश्यकता होती है तो यह शब्दबहुल हो सकता है। एक एसिंक 'फॉर ईच' हेल्पर फ़ंक्शन इटरेशन लॉजिक को समाहित करके इस प्रक्रिया को सरल बना सकता है।
बुनियादी कार्यान्वयन
यहाँ एक एसिंक 'फॉर ईच' फ़ंक्शन का एक बुनियादी कार्यान्वयन है:
async function asyncForEach(iterable, callback) {
for await (const item of iterable) {
await callback(item);
}
}
यह फ़ंक्शन एक एसिंक इटरेबल और एक कॉलबैक फ़ंक्शन को आर्ग्यूमेंट्स के रूप में लेता है। यह for await...of का उपयोग करके इटरेबल पर इटरेट करता है और प्रत्येक आइटम के लिए कॉलबैक फ़ंक्शन को कॉल करता है। यदि आप अगले आइटम पर जाने से पहले इसके पूरा होने का इंतजार करना चाहते हैं तो कॉलबैक फ़ंक्शन भी एसिंक्रोनस होना चाहिए।
उदाहरण: API से डेटा प्रोसेस करना
मान लीजिए कि आप एक API से डेटा प्राप्त कर रहे हैं जो आइटम्स की एक स्ट्रीम लौटाता है। आप प्रत्येक आइटम को आते ही प्रोसेस करने के लिए एसिंक 'फॉर ईच' हेल्पर का उपयोग कर सकते हैं:
async function* fetchDataStream(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
return;
}
// Assuming the API returns JSON chunks
const chunk = decoder.decode(value);
const items = JSON.parse(`[${chunk.replace(/\}\{/g, '},{')}]`); //Split chunks into valid json array
for(const item of items){
yield item;
}
}
} finally {
reader.releaseLock();
}
}
async function processItem(item) {
// Simulate an asynchronous operation
await new Promise(resolve => setTimeout(resolve, 100));
console.log(`Processing item: ${JSON.stringify(item)}`);
}
async function main() {
const apiUrl = 'https://api.example.com/data'; // Replace with your API endpoint
await asyncForEach(fetchDataStream(apiUrl), processItem);
console.log('Finished processing data.');
}
// Example usage
main();
इस उदाहरण में, fetchDataStream API से डेटा प्राप्त करता है और प्रत्येक आइटम को प्राप्त होते ही उत्पन्न (yield) करता है। processItem फ़ंक्शन प्रत्येक आइटम पर एक एसिंक्रोनस ऑपरेशन का अनुकरण करता है। asyncForEach हेल्पर तब इटरेशन और प्रोसेसिंग लॉजिक को सरल बनाता है।
सुधार और विचार
त्रुटि प्रबंधन (Error Handling)
एसिंक्रोनस इटरेशन के दौरान होने वाली त्रुटियों को संभालना महत्वपूर्ण है। आप अपवादों को पकड़ने और संभालने के लिए कॉलबैक फ़ंक्शन को try...catch ब्लॉक में लपेट सकते हैं:
async function asyncForEach(iterable, callback) {
for await (const item of iterable) {
try {
await callback(item);
} catch (error) {
console.error(`Error processing item: ${item}`, error);
// You can choose to re-throw the error or continue processing
}
}
}
समवर्तीता नियंत्रण (Concurrency Control)
डिफ़ॉल्ट रूप से, एसिंक 'फॉर ईच' हेल्पर आइटम को क्रमिक रूप से प्रोसेस करता है। यदि आपको आइटम को समवर्ती रूप से प्रोसेस करने की आवश्यकता है, तो आप समवर्ती ऑपरेशनों की संख्या को सीमित करने के लिए एक प्रॉमिस पूल का उपयोग कर सकते हैं:
async function asyncForEachConcurrent(iterable, callback, concurrency) {
const executing = [];
for await (const item of iterable) {
const p = callback(item).then(() => executing.splice(executing.indexOf(p), 1));
executing.push(p);
if (executing.length >= concurrency) {
await Promise.race(executing);
}
}
await Promise.all(executing);
}
async function processItem(item) {
// Simulate an asynchronous operation
await new Promise(resolve => setTimeout(resolve, 100));
console.log(`Processing item: ${JSON.stringify(item)}`);
}
async function main() {
const apiUrl = 'https://api.example.com/data'; // Replace with your API endpoint
await asyncForEachConcurrent(fetchDataStream(apiUrl), processItem, 5); // Concurrency of 5
console.log('Finished processing data.');
}
इस उदाहरण में, asyncForEachConcurrent समवर्ती कॉलबैक निष्पादन की संख्या को निर्दिष्ट समवर्तीता स्तर तक सीमित करता है। यह बड़ी डेटा स्ट्रीम से निपटने के दौरान प्रदर्शन में सुधार कर सकता है।
रद्दीकरण (Cancellation)
कुछ मामलों में, आपको इटरेशन प्रक्रिया को समय से पहले रद्द करने की आवश्यकता हो सकती है। आप इसे AbortController का उपयोग करके प्राप्त कर सकते हैं:
async function asyncForEach(iterable, callback, signal) {
for await (const item of iterable) {
if (signal && signal.aborted) {
console.log('Iteration aborted.');
return;
}
await callback(item);
}
}
async function main() {
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => {
controller.abort(); // Abort after 2 seconds
}, 2000);
const apiUrl = 'https://api.example.com/data'; // Replace with your API endpoint
await asyncForEach(fetchDataStream(apiUrl), processItem, signal);
console.log('Finished processing data.');
}
इस उदाहरण में, asyncForEach फ़ंक्शन प्रत्येक इटरेशन से पहले signal.aborted प्रॉपर्टी की जाँच करता है। यदि सिग्नल रद्द कर दिया जाता है, तो इटरेशन रोक दिया जाता है।
वास्तविक-दुनिया के अनुप्रयोग
एसिंक इटरेटर और एसिंक 'फॉर ईच' हेल्पर को वास्तविक-दुनिया के परिदृश्यों की एक विस्तृत श्रृंखला में लागू किया जा सकता है:
- डेटा प्रोसेसिंग पाइपलाइन: डेटाबेस या फाइल सिस्टम से बड़े डेटासेट को प्रोसेस करना।
- रीयल-टाइम डेटा स्ट्रीम: वेब सॉकेट, मैसेज क्यू, या सेंसर नेटवर्क से डेटा को संभालना।
- API उपभोग: आइटम्स की स्ट्रीम लौटाने वाले API से डेटा प्राप्त करना और प्रोसेस करना।
- छवि और वीडियो प्रोसेसिंग: बड़ी मीडिया फ़ाइलों को टुकड़ों में प्रोसेस करना।
- लॉग विश्लेषण: बड़ी लॉग फ़ाइलों का लाइन दर लाइन विश्लेषण करना।
उदाहरण - अंतर्राष्ट्रीय स्टॉक डेटा: एक ऐसे एप्लिकेशन पर विचार करें जो विभिन्न अंतर्राष्ट्रीय एक्सचेंजों से रीयल-टाइम स्टॉक कोट्स प्राप्त करता है। डेटा को स्ट्रीम करने के लिए एक एसिंक इटरेटर का उपयोग किया जा सकता है, और एक एसिंक 'फॉर ईच' प्रत्येक कोट को प्रोसेस कर सकता है, जिससे उपयोगकर्ता इंटरफ़ेस नवीनतम कीमतों के साथ अपडेट हो जाता है। इसका उपयोग इन जैसी कंपनियों के मौजूदा स्टॉक रेट प्रदर्शित करने के लिए किया जा सकता है:
- Tencent (चीन): एक प्रमुख अंतर्राष्ट्रीय प्रौद्योगिकी कंपनी के स्टॉक डेटा को प्राप्त करना
- Tata Consultancy Services (भारत): एक अग्रणी आईटी सेवा कंपनी से स्टॉक अपडेट प्रदर्शित करना
- Samsung Electronics (दक्षिण कोरिया): एक वैश्विक इलेक्ट्रॉनिक्स निर्माता से स्टॉक रेट दिखाना
- Toyota Motor Corporation (जापान): एक अंतर्राष्ट्रीय ऑटो निर्माता के स्टॉक की कीमतों की निगरानी करना
निष्कर्ष
एसिंक इटरेटर और एसिंक 'फॉर ईच' हेल्पर जावास्क्रिप्ट में एसिंक्रोनस रूप से डेटा स्ट्रीम को प्रोसेस करने का एक शक्तिशाली और सुरुचिपूर्ण तरीका प्रदान करते हैं। इटरेशन लॉजिक को समाहित करके, आप अपने कोड को सरल बना सकते हैं, पठनीयता में सुधार कर सकते हैं, और अपने एप्लिकेशन के प्रदर्शन को बढ़ा सकते हैं। त्रुटियों को संभालकर, समवर्तीता को नियंत्रित करके, और रद्दीकरण को सक्षम करके, आप मजबूत और स्केलेबल एसिंक्रोनस डेटा प्रोसेसिंग पाइपलाइन बना सकते हैं।