जावा स्क्रिप्ट के अंतर्गत प्रॉमिस एक ऑब्जेक्ट होता है जिसका निर्माण new ऑपरेटर के माध्यम से करने पर उसके भीतर निहित executor फंक्सन रन होता है। इस फंक्शन के रन होने के पश्चात भविष्य में प्रॉमिस दो में से एक स्थिति के अनुसार एक रिजल्ट देता है यदि परिस्थिति अनुकूल है तो प्रॉमिस सक्सेस से संबंधित रिजल्ट देता है और यदि स्थिति विपरीत है तो प्रॉमिस रिजेक्ट से संबंधित फल देता है।
let executorFunction = function(resolve, reject){
// logic here
}
const myPromise = new Promise(executorFunction);
प्रॉमिस के भीतर परिस्थिति के अनुकूल या प्रतिकूल होने से संबंधित कुछ कंडीशन होते हैं। यह कंडीशन एक या एक से अधिक स्टेटमेंट के द्वारा कोड में परिलक्षित होता है। resolve reject में से एक ही कालबैक रन हो सकता हैं इसकी शर्त executorFunction के भीतर होता है
const myPromise = new Promise(function(resolve, reject){
// logic here
});
यहां समझने वाली बात यह है कि executor फंक्सन को दो पैरामीटर पास किया जाता है यह दोनों पैरामीटर वस्तुतः फंक्शंस होते हैं। फंग्शनल प्रोग्रामिंग के सिद्धांत के अनुसार किसी फंक्शन को भी दूसरे फंक्शन के पैरामीटर के रूप में पास किया जा सकता है। ऐसे function parameter को callback कहते हैं।
कहने का अभिप्राय यह हुआ कि हम एग्जीक्यूटर फंक्शन के भीतर दो कॉलबैक फंक्शन को पैरामीटर के रूप में पास करते हैं।
ध्यान दीजिए कि callback function को भी पैरामीटर pass किया जा सकता है और यह किसी भी प्रकार का data हो सकता है और यह एक function भी हो सकता है।
जब एक प्रॉमिस ऑब्जेक्ट को new ऑपरेटर की सहायता से क्रिएट किया जाता है तो वह ऑब्जेक्ट मेमोरी में स्टोर हो जाता है और प्रॉमिस का जो भी कॉलबैक फंक्शन है वह नियत अवधि के बाद रन किया जा सकता है और इसके लिए हमें प्रॉमिस ऑब्जेक्ट को कंज्यूम करना होता है। प्रॉमिस ऑब्जेक्ट को कंज्यूम करने के लिए जो तरीका है वह हम आगे बताते हैं। प्रॉमिस ऑब्जेक्ट को कंज्यूम करने के लिए हम then मेथड का उपयोग करते हैं।
याद रखें की fetch एपीआईं हमें एक प्रॉमिस रिटर्न करता है।
जावास्क्रिप्ट में प्रॉमिस (Promises): Revised
जावास्क्रिप्ट में प्रॉमिस एक ऐसा ऑब्जेक्ट होता है, जो असिंक्रोनस ऑपरेशन (Asynchronous Operation) का परिणाम दर्शाने के लिए उपयोग किया जाता है। इसका निर्माण new ऑपरेटर के माध्यम से किया जाता है। जब प्रॉमिस का निर्माण होता है, तो इसके भीतर एक एग्जीक्यूटर फंक्शन (Executor Function) तुरंत रन होता है। यह फंक्शन भविष्य में होने वाली घटनाओं के आधार पर प्रॉमिस को दो में से किसी एक स्थिति में ले जाता है:
- Fulfilled (Resolved): जब ऑपरेशन सफल होता है।
- Rejected: जब ऑपरेशन असफल होता है।
प्रॉमिस और उसकी कार्यप्रणाली
एग्जीक्यूटर फंक्शन:
जब new Promise लिखा जाता है, तो इसके भीतर एक एग्जीक्यूटर फंक्शन दिया जाता है। यह फंक्शन दो पैरामीटर स्वीकार करता है:
- Resolve: इसे कॉल करने पर प्रॉमिस को Fulfilled स्टेट में ले जाया जाता है।
- Reject: इसे कॉल करने पर प्रॉमिस को Rejected स्टेट में ले जाया जाता है।
एग्जीक्यूटर फंक्शन में ये दोनों पैरामीटर कॉलबैक फंक्शंस (Callback Functions) होते हैं। जावास्क्रिप्ट की फंक्शनल प्रोग्रामिंग की क्षमता के कारण, फंक्शन को पैरामीटर के रूप में पास करना संभव है।
उदाहरण 1: प्रॉमिस का निर्माण और उपयोग
const myPromise = new Promise((resolve, reject) => {
let success = true; // यहां पर किसी कंडीशन को चेक किया जा सकता है
if (success) {
resolve("ऑपरेशन सफल रहा!");
} else {
reject("ऑपरेशन असफल रहा!");
}
});
// प्रॉमिस को कंज्यूम करना
myPromise
.then((message) => {
console.log(`Success: ${message}`);
})
.catch((error) => {
console.log(`Error: ${error}`);
});
आउटपुट (जब success = true):
Success: ऑपरेशन सफल रहा!
आउटपुट (जब success = false):
Error: ऑपरेशन असफल रहा!
इस उदाहरण में, प्रॉमिस ऑब्जेक्ट को कंज्यूम करने के लिए then और catch का उपयोग किया गया है।
- then: यह उस स्थिति को हैंडल करता है जब प्रॉमिस Fulfilled हो।
- catch: यह उस स्थिति को हैंडल करता है जब प्रॉमिस Rejected हो।
एग्जीक्यूटर फंक्शन के पैरामीटर
जैसा कि हमने देखा, एग्जीक्यूटर फंक्शन को दो पैरामीटर (resolve और reject) पास किए जाते हैं। ये दोनों पैरामीटर खुद फंक्शंस होते हैं।
- resolve(data): इस फंक्शन को कॉल करके हम प्रॉमिस को एक सक्सेस स्टेट में ले जाते हैं और साथ में डेटा पास कर सकते हैं।
- reject(error): इस फंक्शन को कॉल करके हम प्रॉमिस को असफल स्टेट में ले जाते हैं और साथ में एरर पास कर सकते हैं।
उदाहरण 2: प्रॉमिस और setTimeout का उपयोग
const delayedPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("डेटा 2 सेकंड बाद प्राप्त हुआ!");
}, 2000);
});
delayedPromise
.then((message) => {
console.log(message);
})
.catch((error) => {
console.log(error);
});
आउटपुट (2 सेकंड बाद):
डेटा 2 सेकंड बाद प्राप्त हुआ!
इस उदाहरण में, setTimeout का उपयोग करके यह दिखाया गया है कि प्रॉमिस का उपयोग असिंक्रोनस ऑपरेशन को नियंत्रित करने के लिए किया जा सकता है।
प्रॉमिस का व्यवहार
- जब एक प्रॉमिस ऑब्जेक्ट new ऑपरेटर के साथ बनाया जाता है, तो वह तुरंत एग्जीक्यूटर फंक्शन को रन करता है।
- प्रॉमिस का रिजल्ट फुलफिल्ड या रिजेक्टेड स्थिति में रहता है।
- प्रॉमिस के स्टेट को नियंत्रित करने के लिए then, catch, और finally का उपयोग किया जाता है।
fetch API और प्रॉमिस
जावास्क्रिप्ट में fetch API एक प्रॉमिस रिटर्न करती है। इसे HTTP कॉल्स के लिए उपयोग किया जाता है।
उदाहरण: fetch और प्रॉमिस
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => {
if (!response.ok) {
throw new Error("नेटवर्क में समस्या है!");
}
return response.json();
})
.then((data) => {
console.log("डेटा प्राप्त हुआ:", data);
})
.catch((error) => {
console.log("एरर:", error);
});
आउटपुट (जब डेटा सफलतापूर्वक प्राप्त हो):
डेटा प्राप्त हुआ: { userId: 1, id: 1, title: "...", body: "..." }
आउटपुट (जब नेटवर्क समस्या हो):
एरर: नेटवर्क में समस्या है!
निष्कर्ष
- प्रॉमिस जावास्क्रिप्ट में असिंक्रोनस ऑपरेशन को संभालने का एक शक्तिशाली टूल है। यह कॉलबैक पद्धति को सरल बनाता है और अधिक पठनीय (Readable) कोड लिखने में मदद करता है।
- प्रॉमिस का उपयोग डेटा फेचिंग, टाइमर बेस्ड ऑपरेशन, और अन्य असिंक्रोनस प्रक्रियाओं को नियंत्रित करने के लिए किया जाता है।
- इसका उचित उपयोग कोड को प्रभावी और त्रुटि-मुक्त बनाने में सहायक है।
Promise Part2
मैं जोर देना चाहता हूँ कि प्रॉमिस के दो चरण है: प्रॉमिस का निर्माण और प्रॉमिस का उपयोग
साथ ही यह भी की प्रॉमिस के executor function के कालबैक मेथड्स कैसे किस किस तरह के data return कर सकते हैं। इस को विस्तार से समझते हैं
जावास्क्रिप्ट में प्रॉमिस: निर्माण और उपयोग
जावास्क्रिप्ट में प्रॉमिस एक ऐसी सुविधा है, जो असिंक्रोनस ऑपरेशन्स (Asynchronous Operations) को संभालने के लिए उपयोग होती है। इसका उद्देश्य कोड को सरल और प्रभावी बनाना है, जिससे लंबे और उलझे हुए कॉलबैक के उपयोग से बचा जा सके।
प्रॉमिस को मुख्यतः दो चरणों में समझा जा सकता है:
- प्रॉमिस का निर्माण (Producing)
- प्रॉमिस का उपयोग (Consuming)
1. प्रॉमिस का निर्माण (Create Promise)
प्रॉमिस का निर्माण new ऑपरेटर और एक एग्जीक्यूटर फंक्शन के माध्यम से किया जाता है। यह चरण उस प्रक्रिया का प्रतिनिधित्व करता है, जहां प्रॉमिस के भीतर डेटा तैयार किया जा रहा होता है।
एग्जीक्यूटर फंक्शन और उसके पैरामीटर
एग्जीक्यूटर फंक्शन दो कॉलबैक फंक्शन्स को पैरामीटर के रूप में स्वीकार करता है:
Resolve callback function: जब ऑपरेशन सफल हो, तब डेटा को निर्मित प्रॉमिस ऑब्जेक्ट में भेजने के लिए इसका उपयोग किया जाता है।
Reject callback function: जब ऑपरेशन असफल हो, तब एरर या समस्या को निर्मित प्रॉमिस में भेजने के लिए इसका उपयोग किया जाता है।
उदाहरण: प्रॉमिस का निर्माण
const myPromise = new Promise((resolve, reject) => {
let isSuccess = true; // ऑपरेशन की स्थिति चेक करें
if (isSuccess) {
resolve("ऑपरेशन सफल रहा!"); // जब ऑपरेशन सफल हो
} else {
reject("ऑपरेशन असफल रहा!"); // जब ऑपरेशन असफल हो
}
});
इस उदाहरण में, myPromise नामक प्रॉमिस ऑब्जेक्ट बनाया गया है।
यदि स्थिति अनुकूल है (isSuccess = true), तो resolve फंक्शन को कॉल किया जाएगा।
यदि स्थिति प्रतिकूल है, तो reject फंक्शन को कॉल किया जाएगा।
2. प्रॉमिस का उपयोग (Consume Promise)
एक बार प्रॉमिस तैयार हो जाने के बाद, इसे कंज्यूम किया जा सकता है। कंज्यूम करने का मतलब है कि प्रॉमिस के परिणाम (Fulfilled या Rejected) के आधार पर प्रतिक्रिया देना।
कंज्यूम करने के लिए मेथड्स
- then: इसे तब उपयोग किया जाता है, जब प्रॉमिस Fulfilled हो।
- catch: इसे तब उपयोग किया जाता है, जब प्रॉमिस Rejected हो।
- finally: इसे हमेशा (चाहे प्रॉमिस Fulfilled हो या Rejected) रन किया जाता है।
उदाहरण: प्रॉमिस का उपयोग
myPromise
.then((message) => {
console.log(`Success: ${message}`); // Fulfilled स्थिति का हैंडलिंग
})
.catch((error) => {
console.log(`Error: ${error}`); // Rejected स्थिति का हैंडलिंग
});
एग्जीक्यूटर फंक्शन से डेटा कैसे लौटाया जाता है?
एग्जीक्यूटर फंक्शन के resolve और reject कॉलबैक्स में किसी भी प्रकार का डेटा पास किया जा सकता है:
सिंपल डेटा (जैसे: string, number)
- resolve("यह एक साधारण संदेश है");
- reject("यह एक त्रुटि संदेश है");
ऑब्जेक्ट या डेटा स्ट्रक्चर
- resolve({ id: 1, name: "John Doe" });
- reject({ errorCode: 404, message: "डेटा नहीं मिला" });
फंक्शन
- resolve(() => console.log("यह एक फंक्शन है"));
असिंक्रोनस डेटा (जैसे: HTTP फेचिंग)
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => response.json())
.then((data) => resolve(data))
.catch((error) => reject(error));
उदाहरण: प्रॉमिस में डेटा लौटाना
const dataPromise = new Promise((resolve, reject) => {
const data = { userId: 1, name: "Rahul" };
resolve(data); // डेटा ऑब्जेक्ट को Resolve करें
});
dataPromise
.then((result) => {
console.log("प्राप्त डेटा:", result);
})
.catch((error) => {
console.log("त्रुटि:", error);
});
आउटपुट:
प्राप्त डेटा: { userId: 1, name: "Rahul" }
Fetch API और प्रॉमिस का उपयोग
fetch API जावास्क्रिप्ट में असिंक्रोनस डेटा फेचिंग के लिए उपयोग होती है और यह हमेशा एक प्रॉमिस रिटर्न करती है।
उदाहरण: Fetch API के साथ प्रॉमिस का उपयोग
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => {
if (!response.ok) {
throw new Error("नेटवर्क में समस्या!");
}
return response.json(); // डेटा को JSON में बदलें
})
.then((data) => {
console.log("डेटा:", data);
})
.catch((error) => {
console.log("त्रुटि:", error);
});
आउटपुट (जब डेटा सफलतापूर्वक प्राप्त हो):
डेटा: { userId: 1, id: 1, title: "...", body: "..." }
प्रॉमिस का लाभ
- कॉलबैक हैल (Callback Hell) से बचाव।
- कोड अधिक पढ़ने योग्य और व्यवस्थित बनता है।
- कई असिंक्रोनस ऑपरेशन्स को आसानी से हैंडल किया जा सकता है।
निष्कर्ष
प्रॉमिस जावास्क्रिप्ट में असिंक्रोनस कोड को बेहतर तरीके से हैंडल करने का एक प्रभावी तरीका है। इसे दो चरणों में समझना सरल बनाता है:
- प्रॉमिस का निर्माण (Producing), जहां डेटा तैयार होता है।
- प्रॉमिस का उपयोग (Consuming), जहां परिणाम का उपयोग किया जाता है।
Promise Part3
अब मैं यह भी बताना चाहता हूं कि जब new ऑपरेटर के द्वारा प्रॉमिस का निर्माण किया जाता है तो वह हिप में कब तक रहता है और कब किस शर्त पर उसके भीतर के कॉल बैक एग्जीक्यूट होते हैं और कब प्रॉमिस को deallocate किया जाता है
जावास्क्रिप्ट में प्रॉमिस: हिप में जीवनकाल और निष्पादन शर्तें
जावास्क्रिप्ट में प्रॉमिस असिंक्रोनस कोड को सरल और प्रबंधनीय बनाने का एक साधन है। जब new ऑपरेटर का उपयोग करके प्रॉमिस का निर्माण किया जाता है, तो यह हिप (Heap) मेमोरी में तब तक रहता है जब तक कि उसे डीलोकेट (Deallocate) नहीं किया जाता। प्रॉमिस का जीवनकाल, निष्पादन, और डीलोकेशन विशिष्ट शर्तों पर आधारित होता है। इस निबंध में हम इन्हीं पहलुओं पर चर्चा करेंगे।
1. प्रॉमिस का निर्माण और हिप में प्रवेश
जब प्रॉमिस का निर्माण new Promise() के माध्यम से किया जाता है:
- जावास्क्रिप्ट प्रॉमिस ऑब्जेक्ट को हिप मेमोरी में संग्रहित करता है।
- इसके साथ ही, एग्जीक्यूटर फंक्शन (Executor Function) को तुरंत निष्पादित किया जाता है।
- एग्जीक्यूटर फंक्शन के भीतर दिए गए resolve और reject कॉलबैक्स केवल तभी निष्पादित होते हैं जब एग्जीक्यूटर फंक्शन अपने कार्य को पूरा कर लेता है।
उदाहरण: प्रॉमिस का निर्माण और हिप में जीवनकाल की शुरुआत
const myPromise = new Promise((resolve, reject) => {
console.log("प्रॉमिस का निर्माण हो रहा है...");
setTimeout(() => {
resolve("डेटा तैयार है");
}, 3000);
});
console.log("प्रॉमिस निर्माण के बाद कोड चलता है");
आउटपुट:
प्रॉमिस का निर्माण हो रहा है...
प्रॉमिस निर्माण के बाद कोड चलता है
(3 सेकंड बाद) डेटा तैयार है
प्रॉमिस का ऑब्जेक्ट हिप में तब तक रहता है, जब तक resolve या reject कॉल नहीं किया जाता।
2. प्रॉमिस के कॉलबैक के निष्पादन की शर्तें
- एग्जीक्यूटर फंक्शन सिंक रूप से (Synchronously) तुरंत रन होता है।
- हालांकि, एग्जीक्यूटर फंक्शन के भीतर resolve और reject असिंक्रोनस ऑपरेशन की स्थिति के आधार पर निष्पादित होते हैं।
- इवेंट लूप और प्रॉमिस: प्रॉमिस का निष्पादन इवेंट लूप (Event Loop) से नियंत्रित होता है।
- जब resolve या reject कॉल किया जाता है, तो प्रॉमिस का परिणाम (Result) माइक्रोटास्क क्यू (Microtask Queue) में भेजा जाता है।
- माइक्रोटास्क क्यू के टास्क तब निष्पादित होते हैं, जब मुख्य कोड (Call Stack) खाली हो जाता है।
उदाहरण: प्रॉमिस के कॉलबैक का समय
console.log("कार्य प्रारंभ");
const myPromise = new Promise((resolve, reject) => {
resolve("प्रॉमिस पूरा हुआ");
});
myPromise.then((result) => {
console.log(result);
});
console.log("कार्य समाप्त");
आउटपुट:
कार्य प्रारंभ
कार्य समाप्त
प्रॉमिस पूरा हुआ
भले ही resolve तुरंत कॉल किया गया हो, इसका परिणाम इवेंट लूप के माध्यम से माइक्रोटास्क क्यू में डालकर बाद में निष्पादित किया जाता है।
हिप में प्रॉमिस कब तक रहता है?
1. तब तक, जब तक प्रॉमिस निष्कर्ष पर न पहुंचे (Pending State):
जब तक प्रॉमिस Pending स्थिति में है, यह हिप में बना रहता है।
Pending स्थिति तब होती है जब resolve या reject को कॉल नहीं किया गया है।
जैसे ही resolve या reject कॉल किया जाता है, प्रॉमिस का निष्कर्ष तय हो जाता है।
2. परिणाम के बाद: तब तक, जब तक सभी उपभोक्ता (Consumers) निष्पादित न हो जाएं:
प्रॉमिस का रिजल्ट हिप में तब तक बना रहता है, जब तक सभी then या catch ब्लॉक्स निष्पादित न हो जाएं।
3. निष्पादन के बाद: मेमोरी से हटाना (Deallocate):
जब प्रॉमिस का परिणाम (Fulfilled या Rejected) सभी उपभोक्ताओं तक पहुंचा दिया जाता है और ऑब्जेक्ट का कोई रेफरेंस नहीं बचता, तो प्रॉमिस हिप मेमोरी से हटा दिया जाता है।
यह काम जावास्क्रिप्ट का Garbage Collector करता है।
4. प्रॉमिस का डीलोकेशन (Deallocation) शर्तें:
- प्रॉमिस का परिणाम तय हो चुका हो।
- ऑब्जेक्ट का कोई और रेफरेंस न बचा हो।
उदाहरण: डीलोकेशन के लिए शर्तें
let myPromise = new Promise((resolve, reject) => {
resolve("डेटा तैयार है");
});
myPromise.then((data) => {
console.log(data);
});
// जब myPromise को null कर दिया जाता है, तो यह डीलोकेट हो सकता है
myPromise = null;
myPromise को null करने पर यह हिप से हटा दिया जाएगा, क्योंकि अब इसका कोई रेफरेंस नहीं है।
प्रॉमिस के जीवनचक्र का सारांश
- निर्माण: new ऑपरेटर के माध्यम से प्रॉमिस हिप में प्रवेश करता है।
- निष्पादन: एग्जीक्यूटर फंक्शन तुरंत निष्पादित होता है, लेकिन resolve और reject असिंक्रोनस रूप से चलते हैं।
- परिणाम: resolve या reject के परिणाम के बाद, प्रॉमिस का परिणाम हिप में तब तक बना रहता है, जब तक सभी उपभोक्ताओं द्वारा उपयोग न हो जाए।
- डीलोकेशन: सभी उपभोक्ताओं के निष्पादित होने और ऑब्जेक्ट का कोई रेफरेंस न बचने पर, प्रॉमिस को गार्बेज कलेक्टर हटा देता है।
उदाहरण: प्रॉमिस का पूरा जीवनचक्र
console.log("कार्य प्रारंभ");
let myPromise = new Promise((resolve, reject) => {
console.log("प्रॉमिस निर्माण हुआ");
setTimeout(() => {
resolve("डेटा तैयार");
}, 2000);
});
myPromise.then((result) => {
console.log(result);
myPromise = null; // डीलोकेशन के लिए तैयार
});
console.log("कार्य समाप्त");
आउटपुट:
कार्य प्रारंभ
प्रॉमिस निर्माण हुआ
कार्य समाप्त
(2 सेकंड बाद) डेटा तैयार
निष्कर्ष
जावास्क्रिप्ट में प्रॉमिस का जीवनचक्र स्पष्ट रूप से परिभाषित है:
- निर्माण (Producing) से प्रारंभ होकर परिणाम (Consuming) तक।
- हिप में प्रॉमिस तब तक बना रहता है, जब तक इसका उपयोग समाप्त नहीं हो जाता।
- जब कोई रेफरेंस शेष नहीं रहता, तो गार्बेज कलेक्टर इसे मेमोरी से हटा देता है।
- यह प्रक्रिया प्रॉमिस के उपयोग को कुशल और संसाधन-संरक्षित बनाती है। विद्यार्थियों को इसे समझने के लिए सरल कोड और प्रयोगों से शुरुआत करनी चाहिए।