यदि आपने कभी फ़ॉर्म सबमिशन बढ़ाने के लिए JavaScript API का उपयोग किया है, तो इस बात की अच्छी संभावना है कि आपने गलती से एक डुप्लिकेट-अनुरोध/रेस-स्थिति बग पेश कर दिया है। आज, मैं आपको समस्या और इससे बचने के अपने सुझावों के बारे में बताऊँगा। fetch (यदि आप चाहें तो वीडियो अंत में) आइए एक बहुत ही बुनियादी पर विचार करें एक इनपुट और सबमिट बटन के साथ। एचटीएमएल फॉर्म <form method="post"> <label for="name">Name</label> <input id="name" name="name" /> <button>Submit</button> </form> जब हम सबमिट बटन दबाते हैं, तो ब्राउजर पूरे पेज को रिफ्रेश करेगा। ध्यान दें कि सबमिट बटन क्लिक करने के बाद ब्राउज़र कैसे पुनः लोड होता है। पृष्ठ ताज़ा करना हमेशा वह अनुभव नहीं होता है जो हम अपने उपयोगकर्ताओं को प्रदान करना चाहते हैं, इसलिए एक सामान्य विकल्प का उपयोग करना है प्रपत्र के "सबमिट" ईवेंट में ईवेंट श्रोता जोड़ने के लिए, डिफ़ॉल्ट व्यवहार को रोकें, और API का उपयोग करके फ़ॉर्म डेटा सबमिट करें। जावास्क्रिप्ट fetch एक सरल दृष्टिकोण नीचे दिए गए उदाहरण की तरह लग सकता है। पेज (या कंपोनेंट) माउंट होने के बाद, हम फॉर्म डोम नोड को पकड़ते हैं, एक ईवेंट श्रोता जोड़ते हैं जो फॉर्म का उपयोग करके एक अनुरोध बनाता है , , और , और हैंडलर के अंत में, हम ईवेंट की विधि कहते हैं। fetch कार्य तरीका आंकड़े preventDefault() const form = document.querySelector('form'); form.addEventListener('submit', handleSubmit); function handleSubmit(event) { const form = event.currentTarget; fetch(form.action, { method: form.method, body: new FormData(form) }); event.preventDefault(); } अब, इससे पहले कि कोई जावास्क्रिप्ट हॉटशॉट GET बनाम POST के बारे में मुझ पर ट्वीट करना शुरू करे और शरीर और अनुरोध करें और जो कुछ भी हो, मुझे बस इतना कहने दो, मुझे पता है। मैं अनुरोध को जानबूझकर सरल रख रहा हूं क्योंकि यह मुख्य फोकस नहीं है। सामग्री प्रकार fetch यहाँ प्रमुख मुद्दा है । यह विधि ब्राउज़र को नया पृष्ठ लोड करने और फ़ॉर्म सबमिट करने के डिफ़ॉल्ट व्यवहार को करने से रोकती है। event.preventDefault() अब, यदि हम स्क्रीन को देखते हैं और सबमिट दबाते हैं, तो हम देख सकते हैं कि पृष्ठ पुनः लोड नहीं होता है, लेकिन हम अपने नेटवर्क टैब में HTTP अनुरोध देखते हैं। ध्यान दें कि ब्राउज़र पूर्ण पृष्ठ पुनः लोड नहीं करता है। दुर्भाग्य से, डिफ़ॉल्ट व्यवहार को रोकने के लिए जावास्क्रिप्ट का उपयोग करके, हमने वास्तव में एक बग पेश किया है जो कि डिफ़ॉल्ट ब्राउज़र व्यवहार में नहीं है। जब हम सादा उपयोग करते हैं और आप सबमिट बटन को वास्तव में जल्दी से कई बार तोड़ देते हैं, आप देखेंगे कि सबसे हाल के अनुरोध को छोड़कर सभी नेटवर्क अनुरोध लाल हो जाते हैं। यह इंगित करता है कि उन्हें रद्द कर दिया गया था, और केवल सबसे हाल के अनुरोध को सम्मानित किया गया है। एचटीएमएल यदि हम इसकी तुलना जावास्क्रिप्ट उदाहरण से करते हैं, तो हम देखेंगे कि सभी अनुरोध भेज दिए गए हैं, और वे सभी रद्द किए बिना पूर्ण हैं। यह एक समस्या हो सकती है क्योंकि हालांकि प्रत्येक अनुरोध में अलग-अलग समय लग सकता है, वे शुरू किए गए समय की तुलना में एक अलग क्रम में हल हो सकते हैं। इसका अर्थ है कि यदि हम उन अनुरोधों के समाधान में कार्यात्मकता जोड़ते हैं, तो हमारे पास कुछ अनपेक्षित व्यवहार हो सकते हैं। एक उदाहरण के रूप में, हम प्रत्येक अनुरोध (" ") के लिए वृद्धि करने के लिए एक चर बना सकते हैं। हर बार जब हम फ़ंक्शन चलाते हैं, तो हम कुल संख्या बढ़ा सकते हैं और वर्तमान अनुरोध (" ") को ट्रैक करने के लिए वर्तमान संख्या को कैप्चर कर सकते हैं। totalRequestCount handleSubmit thisRequestNumber जब एक अनुरोध हल हो जाता है, तो हम कंसोल में इसकी संबंधित संख्या लॉग कर सकते हैं। fetch const form = document.querySelector('form'); form.addEventListener('submit', handleSubmit); let totalRequestCount = 0 function handleSubmit(event) { totalRequestCount += 1 const thisRequestNumber = totalRequestCount const form = event.currentTarget; fetch(form.action, { method: form.method, body: new FormData(form) }).then(() => { console.log(thisRequestNumber) }) event.preventDefault(); } अब, यदि हम उस सबमिट बटन को बार-बार तोड़ते हैं, तो हम कंसोल पर मुद्रित विभिन्न संख्याओं को क्रम से बाहर देख सकते हैं: 2, 3, 1, 4, 5। यह नेटवर्क की गति पर निर्भर करता है, लेकिन मुझे लगता है कि हम सभी सहमत हो सकते हैं कि यह आदर्श नहीं है। एक ऐसे परिदृश्य पर विचार करें जहां एक उपयोगकर्ता निकट उत्तराधिकार में कई को ट्रिगर करता है, और पूरा होने पर, आपका एप्लिकेशन उनके परिवर्तनों के साथ पृष्ठ को अपडेट करता है। ऑर्डर के बाहर समाधान करने के अनुरोध के कारण उपयोगकर्ता अंततः गलत जानकारी देख सकता है। fetch यह गैर-जावास्क्रिप्ट दुनिया में एक गैर-मुद्दा है क्योंकि ब्राउज़र किसी भी पिछले अनुरोध को रद्द कर देता है और सबसे हालिया अनुरोध पूरा होने के बाद पृष्ठ को लोड करता है, सबसे अद्यतित संस्करण को लोड करता है। लेकिन पेज रिफ्रेश उतना सेक्सी नहीं है। जावास्क्रिप्ट प्रेमियों के लिए अच्छी खबर यह है कि हमारे पास दोनों हो सकते हैं और एक सतत यूआई! सेक्सी उपयोगकर्ता अनुभव हमें बस थोड़ा और लेगवर्क करने की जरूरत है। यदि आप एपीआई दस्तावेज़ को देखते हैं, तो आप देखेंगे कि और विकल्पों की प्रॉपर्टी का उपयोग करके फ़ेच को रोकना संभव है। ऐसा कुछ दिखता है: fetch AbortController fetch signal const controller = new AbortController(); fetch(url, { signal: controller.signal }); अनुरोध के लिए का संकेत प्रदान करके, हम किसी भी समय की विधि ट्रिगर होने पर अनुरोध को रद्द कर सकते हैं। fetch AbortContoller AbortContoller abort आप जावास्क्रिप्ट कंसोल में एक स्पष्ट उदाहरण देख सकते हैं। एक बनाने का प्रयास करें, अनुरोध शुरू करें, फिर विधि को तुरंत निष्पादित करें। AbortController fetch abort const controller = new AbortController(); fetch('', { signal: controller.signal }); controller.abort() आपको तुरंत कंसोल पर मुद्रित अपवाद देखना चाहिए। क्रोमियम ब्राउज़र में, यह कहना चाहिए, "अनकॉट (वादे में) DOMException: उपयोगकर्ता ने एक अनुरोध रद्द कर दिया।" और यदि आप नेटवर्क टैब एक्सप्लोर करते हैं, तो आपको स्टेटस टेक्स्ट "(रद्द)" के साथ एक असफल अनुरोध देखना चाहिए। इसे ध्यान में रखते हुए, हम अपने फॉर्म के सबमिट हैंडलर में जोड़ सकते हैं। तर्क इस प्रकार होगा: AbortController सबसे पहले, पिछले किसी भी अनुरोध के लिए की जांच करें। यदि कोई मौजूद है, तो उसे निरस्त करें। AbortController अगला, वर्तमान अनुरोध के लिए एक बनाएं जिसे बाद के अनुरोधों पर निरस्त किया जा सकता है। AbortController अंत में, जब कोई अनुरोध हल हो जाता है, तो उसके संबंधित हटा दें। AbortController ऐसा करने के कई तरीके हैं, लेकिन मैं प्रत्येक सबमिट किए गए DOM नोड और उसके संबंधित के बीच संबंधों को संग्रहीत करने के लिए का उपयोग करूंगा। जब कोई फॉर्म सबमिट किया जाता है, तो हम उसके अनुसार चेक और अपडेट कर सकते हैं। <form> AbortController WeakMap WeakMap const pendingForms = new WeakMap(); function handleSubmit(event) { const form = event.currentTarget; const previousController = pendingForms.get(form); if (previousController) { previousController.abort(); } const controller = new AbortController(); pendingForms.set(form, controller); fetch(form.action, { method: form.method, body: new FormData(form), signal: controller.signal, }).then(() => { pendingForms.delete(form); }); event.preventDefault(); } const forms = document.querySelectorAll('form'); for (const form of forms) { form.addEventListener('submit', handleSubmit); } मुख्य बात एक निरस्त नियंत्रक को इसके संबंधित रूप से संबद्ध करने में सक्षम हो रही है। की कुंजी के रूप में फ़ॉर्म के DOM नोड का उपयोग करना ऐसा करने का एक सुविधाजनक तरीका है। WeakMap इसके साथ, हम अनुरोध के लिए का संकेत जोड़ सकते हैं, किसी भी पिछले नियंत्रक को निरस्त कर सकते हैं, नए जोड़ सकते हैं, और पूरा होने पर उन्हें हटा सकते हैं। fetch AbortController उम्मीद है, यह सब समझ में आता है। अब, यदि हम उस फॉर्म के सबमिट बटन को कई बार तोड़ते हैं, तो हम देख सकते हैं कि नवीनतम को छोड़कर सभी एपीआई अनुरोध रद्द हो जाते हैं। इसका मतलब यह है कि HTTP प्रतिक्रिया का जवाब देने वाला कोई भी फ़ंक्शन आपकी अपेक्षा के अनुरूप अधिक व्यवहार करेगा। अब, यदि हम उसी गिनती और लॉगिंग लॉजिक का उपयोग करते हैं जो हमारे ऊपर है, तो हम सबमिट बटन को सात बार स्मैश कर सकते हैं और कंसोल में छह अपवाद ( के कारण) और "7" का एक लॉग देखेंगे। AbortController यदि हम फिर से सबमिट करते हैं और अनुरोध को हल करने के लिए पर्याप्त समय देते हैं, तो हमें कंसोल में "8" दिखाई देगा। और अगर हम सबमिट बटन को कई बार तोड़ते हैं, तो हम अपवादों और अंतिम अनुरोध की गिनती को सही क्रम में देखना जारी रखेंगे। यदि आप अनुरोध के निरस्त होने पर कंसोल में DOMExceptions को देखने से बचने के लिए कुछ और तर्क जोड़ना चाहते हैं, तो आप अपने के बाद एक ब्लॉक जोड़ सकते हैं और जांच सकते हैं कि क्या त्रुटि का नाम " " से मेल खाता है: fetch .catch() AbortError fetch(url, { signal: controller.signal, }).catch((error) => { // If the request was aborted, do nothing if (error.name === 'AbortError') return; // Otherwise, handle the error here or throw it back to the console throw error }); समापन यह पूरी पोस्ट जावास्क्रिप्ट-वर्धित रूपों पर केंद्रित थी, लेकिन जब भी आप एक अनुरोध करते हैं तो शामिल करना शायद एक अच्छा विचार है। यह वास्तव में बहुत बुरा है कि यह पहले से ही एपीआई में नहीं बनाया गया है। लेकिन उम्मीद है, यह आपको इसे शामिल करने का एक अच्छा तरीका दिखाता है। fetch AbortController यह भी उल्लेखनीय है कि यह दृष्टिकोण उपयोगकर्ता को सबमिट बटन को कई बार स्पैम करने से नहीं रोकता है। बटन अभी भी क्लिक करने योग्य है, और अनुरोध अभी भी बंद हो जाता है, यह प्रतिक्रियाओं से निपटने का एक अधिक सुसंगत तरीका प्रदान करता है। दुर्भाग्य से, यदि कोई उपयोगकर्ता सबमिट बटन को स्पैम , तो वे अनुरोध अभी भी आपके बैकएंड पर जाएंगे और अनावश्यक संसाधनों के एक समूह का उपयोग कर सकते हैं। करता है कुछ सहज समाधान सबमिट बटन को अक्षम कर सकते हैं, a , या केवल पिछले अनुरोधों के समाधान के बाद नए अनुरोध बनाना। मुझे ये विकल्प पसंद नहीं हैं क्योंकि वे उपयोगकर्ता के अनुभव को धीमा करने पर भरोसा करते हैं और केवल ग्राहक पक्ष पर काम करते हैं। debounce वे स्क्रिप्टेड अनुरोधों के माध्यम से दुरुपयोग को संबोधित नहीं करते हैं। अपने सर्वर पर बहुत अधिक अनुरोधों से होने वाले दुरुपयोग को संबोधित करने के लिए, आप शायद कुछ सेट अप करना चाहेंगे . यह इस पोस्ट के दायरे से बाहर है, लेकिन यह उल्लेखनीय था। दर सीमित यह भी उल्लेखनीय है कि दर सीमित करने से डुप्लिकेट अनुरोधों, दौड़ की स्थितियों और असंगत यूआई अपडेट की मूल समस्या का समाधान नहीं होता है। आदर्श रूप से, हमें दोनों सिरों को ढकने के लिए दोनों का उपयोग करना चाहिए। वैसे भी, मेरे पास आज के लिए बस इतना ही है। यदि आप इसी विषय पर एक वीडियो देखना चाहते हैं, तो इसे देखें। https://www.youtube.com/watch?v=w8ZIoLnh1Dc&embedable=true पढ़ने के लिए आपको बहुत बहुत शुक्रिया। अगर आपको यह लेख पसंद आया हो तो प्लीज . यह मेरा समर्थन करने के सर्वोत्तम तरीकों में से एक है। आप भी कर सकते हैं या यदि आप जानना चाहते हैं कि नए लेख कब प्रकाशित होते हैं। इसे शेयर करें मेरे न्यूज़लैटर के लिए साइन अप करें ट्विटर पर मुझे फॉलो करें मूल रूप से पर प्रकाशित किया गया austingil.com .