ES6 में पेश किए गए, प्रॉमिसेस आपको विभिन्न कॉलबैक फंक्शन्स से निपटने के बिना आसानी से एसिंक्रोनस कोड लिखने की अनुमति देते हैं। प्रॉमिसेस के साथ, मल्टी-लेवल कॉलबैक फंक्शन्स के बारे में चिंता करने की कोई आवश्यकता नहीं है जो लिखने और बनाए रखने दोनों में कठिन होते हैं।
जावास्क्रिप्ट में एक और फीचर है जो प्रॉमिसेस का उपयोग करके एसिंक्रोनस कोड लिखना और भी आसान बनाता है: async/await फंक्शन्स। ये आपको ऐसा कोड लिखने की अनुमति देते हैं जो सिंक्रोनस दिखता है लेकिन वास्तव में एसिंक्रोनस रूटीन करता है।
इस गाइड में, हम चर्चा करेंगे कि async/await फंक्शन क्या है और आप इसे अपने कोड में कैसे उपयोग कर सकते हैं। आइए शुरू करें!
प्रॉमिसेस: एक पुनरावलोकन
इससे पहले कि हम async/await फंक्शन्स के बारे में बात करना शुरू करें, हमें प्रॉमिसेस का पुनरावलोकन करने की आवश्यकता है। एक प्रॉमिस एक एसिंक्रोनस ऑपरेशन को दर्शाता है। यह आपके कोड को बताता है कि एक ऑपरेशन किया जाने वाला है और, यदि ऑपरेशन सफल होता है, तो एक मान लौटाया जाएगा। अन्यथा, आपके प्रोग्राम के बाकी हिस्से में एक त्रुटि लौटाई जाएगी।
एक प्रॉमिस एक ऐसे मान को दर्शाता है जो प्रॉमिस बनाए जाने पर ज्ञात नहीं होता। एक प्रॉमिस बस यही है: एक वादा कि भविष्य के मान आपके कोड को वापस भेज दिए जाएंगे। क्योंकि प्रॉमिस एक ऑब्जेक्ट है, इसे कैपिटलाइज़ किया जाना चाहिए।
इस परिदृश्य पर विचार करें। आपको एक API से संसाधन पुनर्प्राप्त करने की आवश्यकता है। आपके अनुरोध को प्रोसेस होने में एक या दो सेकंड लगेंगे। अनुरोध प्रोसेस होने के लिए उपयोगकर्ता को प्रतीक्षा कराने के बजाय, आप अपने कोड को प्रॉमिस में ले जा सकते हैं ताकि आपके प्रोग्राम का बाकी हिस्सा चलता रहे।
इसका मतलब है कि आप अपने वेबसाइट के यूजर इंटरफेस के कुछ हिस्से को रेंडर करना जारी रख सकते हैं जबकि डेटा पुनर्प्राप्त किया जा रहा है। जैसे ही मान लौटाया जाता है, प्रॉमिस इसे आपके मुख्य प्रोग्राम को भेज देगा।
यहां प्रॉमिस का एक उदाहरण है:
let sendCookies = new Promise(resolve => { setTimeout(() => { resolve("Your cookies have been sent!"); }, 1000); }); sendCookies.then(data => { console.log(data); })
हमारा कोड रिटर्न करता है: Your cookies have been sent! जब हम sendCookies.then() मेथड को एक्जीक्यूट करते हैं, तो हमारा प्रॉमिस शुरू होता है। हमारा प्रोग्राम 1,000 मिलीसेकंड प्रतीक्षा करता है और फिर मान "Your cookies have been sent!" को हमारे मुख्य प्रोग्राम में वापस भेजता है।
Async और Await का उपयोग कैसे करें
async/await फंक्शन में, एक await स्टेटमेंट अपने async फंक्शन के भीतर कोड को एक्जीक्यूट होने से तब तक रोकता है जब तक प्रॉमिस लौटाया नहीं जाता। इसी कारण से डेवलपर्स अक्सर कहते हैं कि async/await फंक्शन्स सिंक्रोनस दिखते हैं लेकिन एसिंक्रोनस कार्य करते हैं।
निम्न उदाहरण पर विचार करें:
function sendCookies() { return new Promise(resolve => { setTimeout(() => { resolve("Your cookies have been sent!"); }, 1000); }); } async function main() { const sendMessage = await sendCookies(); console.log(sendMessage); } main();
हमारा कोड रिटर्न करता है: Your cookies have been sent! हमारे sendCookies() फंक्शन को "Your cookies have been sent" मान लौटाने में 1,000 मिलीसेकंड लगते हैं। इस मामले में, हमने एक async फंक्शन घोषित किया है ताकि हमारा कोड प्रॉमिस के रिजॉल्व या रिजेक्ट होने की प्रतीक्षा करे।
"async" कीवर्ड हमारे कोड को बताता है कि हम अपने फंक्शन में एसिंक्रोनस ऑपरेशन करना चाहते हैं। "await" कीवर्ड हमारे कोड को sendCookies() प्रॉमिस की वापसी की प्रतीक्षा करने के लिए कहता है इससे पहले कि यह हमारे प्रोग्राम को एक्जीक्यूट करना जारी रखे।
Async फंक्शन्स हमेशा एक प्रॉमिस लौटाते हैं।
कई चरणों के साथ Async और Await का उपयोग करना
Async/await फंक्शन्स सबसे अधिक तब उपयोग किए जाते हैं जब कई प्रॉमिसेस होते हैं जिनके साथ आपको काम करने की आवश्यकता होती है। इसे कभी-कभी प्रॉमिसेस चेनिंग कहा जाता है। ऐसा इसलिए है क्योंकि आपका कोड अगले चरण पर जाने से पहले प्रत्येक चरण द्वारा लौटाए गए प्रॉमिस की प्रतीक्षा करेगा:
function processOrder() { return new Promise(resolve => { setTimeout(() => { resolve("Your cookie order is being processed..."); }, 1000); }); } function sendCookies() { return new Promise(resolve => { setTimeout(() => { resolve("Your cookies have been sent!"); }, 1000); }); } async function main() { const processingMessage = await processOrder(); console.log(sendMessage); const sendMessage = await sendCookies(); console.log(sendMessage); }
हमारा कोड रिटर्न करता है:
Your cookie order is being processed… Your cookies have been sent!
प्रत्येक चरण को पूरा होने में 1,000 मिलीसेकंड लगते हैं। हमारा sendCookies() फंक्शन तब तक एक्जीक्यूट नहीं होता जब तक हमारे processOrder() फंक्शन का प्रॉमिस नहीं लौटाया जाता।
Async एक्सप्रेशन्स
async/await फंक्शन का उपयोग करने के तीन तरीके हैं।
पहला तरीका वह दृष्टिकोण है जिसे हमने अपने पिछले उदाहरणों में दिखाया है: फंक्शन्स घोषित करके। हमारे उदाहरणों में हमने फंक्शन्स घोषित किए हैं जो प्रॉमिस लौटाते हैं, फिर हमने उन फंक्शन्स को एक्जीक्यूट करने के लिए "async" और "await" कीवर्ड्स का उपयोग किया।
आप ऐरो फंक्शन्स का उपयोग करके भी async फंक्शन घोषित कर सकते हैं:
const main = async () => { const sendMessage = await sendCookies(); console.log(sendMessage); }
यह कोड रिटर्न करता है: Your cookies have been sent! यह हमारे पहले उदाहरण के समान है लेकिन main() फंक्शन घोषित करने के बजाय, हमने ऐरो फंक्शन का उपयोग किया है।
इसी तरह, आप फंक्शन एक्सप्रेशन सिंटैक्स का उपयोग कर सकते हैं:
const main = async function() { const sendMessage = await sendCookies(); console.log(sendMessage); }
यह कोड रिटर्न करता है: Your cookies have been sent! जैसा कि आप देख सकते हैं, आउटपुट एक बार फिर समान है। अंतर केवल यह है कि हमने अपना फंक्शन कैसे घोषित किया है।
वास्तव में, यह सिंटैक्स हमारे पिछले उदाहरण के बहुत समान है। हमने ऐरो फंक्शन के बजाय "function()" कीवर्ड का उपयोग किया है।
async/await फंक्शन घोषित करने का कोई सर्वोत्तम तरीका नहीं है। यह सब उस प्रोग्राम पर निर्भर करता है जिसे आप लिख रहे हैं और आप कौन सा सिंटैक्स पसंद करते हैं। जबकि आप तर्क दे सकते हैं कि ऐरो फंक्शन्स सबसे संक्षिप्त मेथड है, async/await फंक्शन घोषित करने के अन्य तरीके अन्य मामलों में बेहतर हो सकते हैं।
Async/Await का उपयोग करके वेब अनुरोध प्रोसेस करना
async/await फंक्शन के सबसे आम उपयोगों में से एक है fetch() जैसे प्रॉमिस-बेस्ड API के साथ वेब अनुरोधों को प्रोसेस करना। fetch() फंक्शन का उपयोग कैसे करें, इसके बारे में अधिक पढ़ने के लिए जावास्क्रिप्ट fetch के लिए हमारे शुरुआती गाइड को पढ़ें।
इस उदाहरण पर विचार करें:
async function retrieveComments() { const res = await fetch('https://jsonplaceholder.typicode.com/comments'); var comments = await res.json(); comments = comments.map(comment => comment.name); console.log(comments); } retrieveComments();
हमारा कोड रिटर्न करता है:
["id labore ex et quam laborum", "quo vero reiciendis velit similique earum" …]
जब हम अपना retrieveComments() फंक्शन एक्जीक्यूट करते हैं, तो हम अपने fetch() स्टेटमेंट को चलाने की प्रतीक्षा करने के लिए "await" कीवर्ड का उपयोग करते हैं। इसका मतलब है कि हमारे प्रोग्राम का बाकी हिस्सा तब तक जारी नहीं रहता जब तक हमारा वेब अनुरोध प्रोसेस नहीं हो जाता। ऐसा इसलिए है क्योंकि fetch() फंक्शन प्रॉमिस लौटाता है।
जब fetch() फंक्शन द्वारा प्रॉमिस लौटाया जाता है, तो हम उसके द्वारा लौटाए गए मान को JSON में बदलते हैं। फिर हम ऑब्जेक्ट के माध्यम से मैप करते हैं ताकि सभी कमेंट्स के नामों की सूची पुनर्प्राप्त कर सकें और उस सूची को कंसोल पर प्रिंट कर सकें।
त्रुटि को कैसे संभालें
काश, कोड में त्रुटियां नहीं होतीं। लेकिन होती हैं, और यह कुछ ऐसा है जिसे हमें डेवलपर्स के रूप में योजना बनानी पड़ती है। एसिंक्रोनस फंक्शन में, त्रुटि प्रबंधन try…catch स्टेटमेंट का उपयोग करके सिंक्रोनस रूप से किया जाता है। इस कोड पर विचार करें:
async function retrieveCookies() { const res = await fetch('https://thisapidoesnotexist.app/cookies'); var cookieNames = await res.json(); cookieNames = cookieNames.map(cookie => cookie.name); resolve(cookieNames); } async function printCookies() { const cookies = await retrieveCookies(); console.log(cookies); } printCookies().catch(res => console.log(res.message));
हमारा कोड रिटर्न करता है:
NetworkError when attempting to fetch resource. जबकि हमारा कोड कार्यात्मक है, हम जिस API को एक्सेस करने का प्रयास कर रहे हैं वह मौजूद नहीं है। इसका मतलब है कि हमारा प्रॉमिस कोई डेटा नहीं लौटा सकता, इसलिए यह इसके बजाय एक रिजेक्टेड प्रॉमिस लौटाता है।
हमारे उदाहरण में, हमने अपनी फंक्शन द्वारा लौटाई गई त्रुटि को प्रिंट करने के लिए .catch() स्टेटमेंट का उपयोग किया है यदि कोई लौटाई जाती है। इस मामले में, हम अपने कोड को बताने के लिए reject('Error') का उपयोग करते हैं कि एक त्रुटि उत्पन्न हुई है।
यदि यह स्टेटमेंट एक्जीक्यूट होता है, तो हमारा .catch() स्टेटमेंट एक्शन में आता है और उस त्रुटि को प्रिंट करता है।
इसी तरह, async फंक्शन्स सिंटैक्स त्रुटियों को पकड़ सकते हैं:
async function retrieveCookies() { const res = await fetch('https://thisapidoesnotexist.app/cookies'); var cookieNames = await res.json(); cookieNames = cookieNames.map(cookie => cookie.name); resolve(cookieNames); } async function printCookies() { try { const cookies = await retrieveCookies(); console.log(cookies); } catch(error) { console.log(error); } } printCookies();
हमारा कोड रिटर्न करता है: NetworkError when attempting to fetch resource. इस उदाहरण में, हमने यह जांचने के लिए try/catch स्टेटमेंट का उपयोग किया है कि क्या हमारे await मेथड ने सफल प्रॉमिस लौटाया है। फिर से, हमारा API मान्य नहीं है, जिससे हमारा प्रोग्राम हमारे प्रॉमिस को रिजेक्ट कर देता है। जब ऐसा होता है, तो हमारे try/catch ब्लॉक में "catch" स्टेटमेंट एक्जीक्यूट होता है, जो हमारी त्रुटि को कंसोल पर लॉग करता है।
निष्कर्ष
Async/await फंक्शन्स आपको अपने कोड में एसिंक्रोनस ऑपरेशन लिखने में मदद करते हैं। जब एक async फंक्शन घोषित किया जाता है, तो आप ऑपरेशन के रिजॉल्व होने की प्रतीक्षा करने के लिए "await" कीवर्ड का उपयोग कर सकते हैं। await कीवर्ड का उपयोग उस फंक्शन के साथ किया जाना चाहिए जो प्रॉमिस लौटाता है।
अब आप एक विशेषज्ञ की तरह async/await जावास्क्रिप्ट फंक्शन्स का उपयोग करना शुरू करने के लिए तैयार हैं!