जब ब्राउज़र कोई खिलौना नहीं, बल्कि डेटा-सेंटर है
\n\nहम इस बात के आदी हैं कि जावास्क्रिप्ट ब्राउज़र के सैंडबॉक्स में रहता है: एनिमेशन, क्लिक, फ़ॉर्म। लेकिन क्या होगा अगर मैं कहूँ कि शुद्ध JS पर 500 MB की CSV फ़ाइल को प्रोसेस किया जा सकता है, 100,000 बिंदुओं का ग्राफ़ बनाया जा सकता है और टैब को हैंग किए बिना? यह कल्पना नहीं है, बल्कि जावास्क्रिप्ट पर बड़े डेटा प्रसंस्करण का कुशल उपयोग है।
\nइस लेख में, मैं दिखाऊंगा कि बड़ी मात्रा में डेटा के साथ सीधे ब्राउज़र में कैसे काम करें - बिना बैकएंड, बिना Python, बिना सर्वर पर गीगाबाइट कॉपी किए। आप स्ट्रीमिंग, वेब वर्कर्स, मेमोरी ऑप्टिमाइज़ेशन और उन लाइब्रेरीज़ के बारे में जानेंगे जो ब्राउज़र को एक मिनी-डेटा-प्रोसेसर में बदल देती हैं। चलिए शुरू करते हैं!
\n\nक्यों "भोला" डेटा प्रसंस्करण प्रदर्शन को मार देता है
\nकल्पना करें: आप 300 MB की CSV फ़ाइल लोड करते हैं और लिखते हैं:
\nconst data = await response.json(); // ❌ घातक त्रुटि\nक्या होता है? JS पूरी फ़ाइल को RAM में पार्स करने की कोशिश करता है। अगर उपयोगकर्ता के पास 4 GB RAM है - ब्राउज़र क्रैश हो जाएगा। शक्तिशाली PC पर भी, गार्बेज कलेक्टर "धीमा" होने लगेगा, और इंटरफ़ेस एक मिनट के लिए फ़्रीज़ हो जाएगा।
\nनियम #1: सब कुछ एक साथ लोड न करें। जावास्क्रिप्ट पर बड़े डेटा के लिए स्ट्रीमिंग प्रोसेसिंग और चंक्स में विभाजन की आवश्यकता होती है।
\n\nडेटा स्ट्रीमिंग: फ़ाइल को टुकड़ों में पढ़ना
\nब्राउज़र API FileReader फ़ाइल को भागों में पढ़ने की अनुमति देता है। लेकिन इससे भी अधिक सुविधाजनक है ReadableStream। उदाहरण: बड़ी JSON फ़ाइल को लाइन दर लाइन प्रोसेस करना।
उदाहरण: NDJSON के साथ JSON स्ट्रीमिंग
\nNDJSON फ़ॉर्मेट (प्रत्येक पंक्ति एक अलग JSON ऑब्जेक्ट है) बड़े डेटा के लिए आदर्श है। इसे स्ट्रीम के रूप में कैसे पढ़ें:
\nasync function* streamJSON(file) {\n const stream = file.stream();\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop(); // बाकी बफर में\n for (const line of lines) {\n if (line.trim()) yield JSON.parse(line);\n }\n }\n}\n\n// उपयोग\nfor await (const obj of streamJSON(selectedFile)) {\n processRow(obj); // एक-एक करके ऑब्जेक्ट प्रोसेस करें\n}\n\nमेमोरी लगभग नहीं बढ़ती - हम इसमें केवल एक लाइन रखते हैं। यह दृष्टिकोण वास्तविक परियोजनाओं में जावास्क्रिप्ट बड़े डेटा प्रसंस्करण का आधार है।
\n\nवेब वर्कर्स: इंटरफ़ेस को हैंग न करें
\nस्ट्रीमिंग भी मुख्य थ्रेड में निष्पादित होती है। यदि गणना जटिल है - UI फ़्रीज़ हो जाएगा। समाधान: वेब वर्कर्स। यह एक अलग थ्रेड है जहाँ बिना लैग के गीगाबाइट चलाए जा सकते हैं।
\n\nCSV प्रसंस्करण के लिए वर्कर बनाना
\nवर्कर कोड (worker.js):
\nself.onmessage = async function(e) {\n const { file, chunkSize } = e.data;\n const reader = new FileReaderSync(); // सिंक्रोनस रीडिंग - वर्कर के लिए ठीक है\n let offset = 0;\n const results = [];\n\n while (offset < file.size) {\n const blob = file.slice(offset, offset + chunkSize);\n const text = reader.readAsText(blob);\n const lines = text.split('\\n');\n for (const line of lines) {\n if (line.trim()) results.push(parseCSVLine(line));\n }\n offset += chunkSize;\n // मध्यवर्ती परिणाम भेजें\n self.postMessage({ type: 'chunk', data: results.splice(0, results.length) });\n }\n self.postMessage({ type: 'done' });\n};\n\nfunction parseCSVLine(line) {\n const [name, age, city] = line.split(',');\n return { name, age: parseInt(age), city };\n}\n\nमुख्य थ्रेड:
\nconst worker = new Worker('worker.js');\nworker.postMessage({ file: csvFile, chunkSize: 1024 * 1024 }); // 1 MB चंक्स\n\nworker.onmessage = (e) => {\n if (e.data.type === 'chunk') {\n updateUI(e.data.data); // टेबल/ग्राफ़ को सुचारू रूप से अपडेट करें\n }\n};\n\nअब इंटरफ़ेस रिस्पॉन्सिव रहता है, भले ही हम 2 GB डेटा प्रोसेस कर रहे हों। यह b के लिए मुख्य तकनीक है