दिलचस्प पोस्ट
संपादन टेक्स्ट के अंदर निरंतर पाठ रखें जो गैर-संपादन योग्य होना चाहिए – एंड्रॉइड PHP का उपयोग करते हुए ईमेल कैसे भेजें? SQL सर्वर के लिए "पसंद" और "IN" का संयोजन जावास्क्रिप्ट अभिव्यक्ति में अल्पविराम क्या करता है? स्पर्क एमएल लिब में टीएफ वेक्टर आरडीडी से शब्द विवरण कैसे प्राप्त करें? PHP में यादृच्छिक पासवर्ड उत्पन्न करना विधानसभा संसाधन स्ट्रीम से डिस्क पर फ़ाइल लिखें फ्रैगमेंट के सेट को समझना रिटाइन इन्स्टेंस (बूलियन) जावा कचरा कलेक्टर – यह कब एकत्र करता है? क्रोम एक्सटेंशन – जीमेल के मूल संदेश को पुनः प्राप्त करना कंट्रोलर वैश्विक रूप से नियंत्रकों को परिभाषित करते हुए, एक समारोह नहीं, अपरिभाषित हो गया बाकी – JSON के साथ HTTP पोस्ट बहुपंक्ति सीमा से 2 आयामी सरणी एनएसबीएलऑनपरेशन और कतारों के साथ NSURL सत्र अजाक्स प्रसंस्करण में "अमान्य JSON पुरानी"

झुकाव ने अस्वीकृति पर गुजरने का वादा किया

मुझे समझ में एक समस्या है कि एक वायदेय श्रृंखला के माध्यम से अस्वीकार क्यों नहीं किया गया है और मुझे उम्मीद है कि किसी ने मुझे यह समझने में मदद कर सकूँगा कि क्यों मुझे, वादों की एक श्रृंखला के लिए कार्यक्षमता संलग्न करने का इरादा है कि मैं पूरा होने के मूल वादे पर निर्भर हूं। यह समझाना कठिन है, तो मुझे पहले मेरी समस्या का एक कोड उदाहरण दिखाएं। (ध्यान दें: यह उदाहरण नोड और आस्थगित नोड मॉड्यूल का उपयोग कर रहा है I Dojo 1.8.3 के साथ इसका परीक्षण किया और इसका एक ही परिणाम था)

var d = require("deferred"); var d1 = d(); var promise1 = d1.promise.then( function(wins) { console.log('promise1 resolved'); return wins;}, function(err) { console.log('promise1 rejected'); return err;}); var promise2 = promise1.then( function(wins) { console.log('promise2 resolved'); return wins;}, function(err) { console.log('promise2 rejected'); return err;}); var promise3 = promise2.then( function(wins) { console.log('promise3 resolved'); return wins;}, function(err) { console.log('promise3 rejected'); return err;}); d1.reject(new Error()); 

इस ऑपरेशन को चलाने के परिणाम यह आउटपुट हैं:

 promise1 rejected promise2 resolved promise3 resolved 

ठीक है, मेरे लिए, यह परिणाम मतलब नहीं है। इस वादे श्रृंखला के साथ जुड़कर, प्रत्येक तो यह आशय का अर्थ दे रहा है कि यह डी 1 के सफल समाधान पर निर्भर होगा और परिणाम श्रृंखला के नीचे दिया जा रहा है। अगर वादा 1 में वादा करता है तो जीत मूल्य प्राप्त नहीं होता है, लेकिन इसकी त्रुटि हैंडलर में इसके बजाय एक गलती मूल्य मिलता है, श्रृंखला में अगले वादे के लिए यह कैसे सफल हो सकता है कि इसकी सफलता का नाम है? इसका कोई मतलब नहीं है कि यह अगले वादे के लिए एक सार्थक मूल्य पर पारित कर सकता है क्योंकि उसे मूल्य ही नहीं मिला।

एक अलग तरह से मैं जो कुछ सोच रहा हूं वर्णन कर सकता हूं: तीन लोग, जॉन, अदरक, और बॉब हैं I जॉन एक विजेट की दुकान का मालिक है अदरक उसकी दुकान में आता है और मिश्रित रंगों के विगेट्स के एक बैग का अनुरोध करता है। उनके पास स्टॉक में नहीं है, इसलिए वह अपने वितरक से अनुरोध करता है कि उन्हें उन्हें भेज दिया जाए। मतलब समय में, वह अदरक को एक बारिश की जांच करता है जिसमें वह बताता है कि उसे विजेट्स का बैग देना है। बॉब ने पाया कि अदरक विगेट्स और अनुरोध प्राप्त कर रहा है कि जब वह उनके साथ किया जाता है तो उसे नीले विजेट मिल जाता है। वह इससे सहमत हैं और उसे बताती है कि वह करेंगे अब, जॉन की वितरक अपनी आपूर्ति में कोई भी विजेट नहीं पा सकते हैं और निर्माता उन्हें और नहीं बनाते हैं, इसलिए वे जॉन को सूचित करते हैं, जो बदले में अदरक को सूचित करते हैं कि वह विजेट नहीं पा सकते हैं। जब कोई खुद को नहीं मिला तो बॉब अदरक से एक नीला विजेट कैसे प्राप्त कर सकता है?

इस मुद्दे पर मेरे पास तीसरे और अधिक यथार्थवादी परिप्रेक्ष्य यह है। कहो कि मुझे दो मान हैं जो मुझे डेटाबेस में अद्यतन करना चाहते हैं। एक दूसरे के आईडी पर निर्भर करता है, लेकिन मैं आईडी प्राप्त नहीं कर सकता जब तक कि मैंने इसे पहले ही एक डाटाबेस में डाला न हो और परिणाम प्राप्त कर लिया। उस के शीर्ष पर, पहली प्रविष्टि डेटाबेस से एक क्वेरी पर निर्भर होती है। डाटाबेस कॉल करने वाले वादे करता है कि मैं दो कॉल को एक अनुक्रम में चेन के लिए उपयोग करता हूं।

 var promise = db.query({parent_id: value}); promise.then(function(query_result) { var first_value = { parent_id: query_result[0].parent_id } var promise = db.put(first_value); promise.then(function(first_value_result) { var second_value = { reference_to_first_value_id: first_value_result.id } var promise = db.put(second_value); promise.then(function(second_value_result) { values_successfully_entered(); }, function(err) { return err }); }, function(err) { return err }); }, function(err) { return err }); 

अब, इस परिस्थिति में, अगर db.query विफल हो गया है, तो यह पहले की गलती समारोह को कॉल करेगा। लेकिन फिर यह अगले वादे के सफलता समारोह को फोन करेगा। हालांकि यह वादा पहले मूल्य के परिणामों की उम्मीद कर रहा है, इसके बजाय इसके त्रुटि हैंडलर फ़ंक्शन से त्रुटि संदेश प्राप्त होगा।

तो, मेरा प्रश्न यह है कि यदि मुझे अपनी सफलता समारोह में त्रुटियों के लिए परीक्षण करना है, तो मुझे फ़ंक्शन देने में त्रुटि क्यों होगी?

इस की लंबाई के लिए क्षमा करें मुझे नहीं पता था कि यह कैसे एक और रास्ता समझाए।

अद्यतन और सुधार

(ध्यान दें: मैंने एक प्रतिक्रिया को हटा दिया था, जो मैंने एक बार कुछ टिप्पणियों के लिए किया था, इसलिए यदि कोई मेरी प्रतिक्रिया पर टिप्पणी करता है, तो उनकी टिप्पणियां अब संदर्भ से बाहर लग सकती हैं I इसे हटा दिया गया है। इसके लिए क्षमा करें, मैं इसे यथासंभव कम रखने की कोशिश कर रहा हूं ।)

आपको धन्यवाद जो सभी ने उत्तर दिया मैं सबसे पहले मेरे प्रश्न को इतनी खराब, विशेष रूप से मेरा छद्म कोड लिखने के लिए सभी के लिए माफी मांगना चाहता हूं। मैं इसे कम रखने की कोशिश में थोड़ा बहुत आक्रामक था।

बर्गी की प्रतिक्रिया के लिए धन्यवाद, मुझे लगता है कि मुझे अपने तर्क में त्रुटि मिली मुझे लगता है कि मैं एक और समस्या की अनदेखी कर सकता था जो कि मेरे लिए समस्या पैदा कर रहा था। यह संभवत: वादा श्रृंखला का काम करता है क्योंकि मैंने सोचा था कि यह होना चाहिए। मैं अब भी अपने कोड के विभिन्न तत्वों का परीक्षण कर रहा हूं, इसलिए मैं यह भी देख पाने के लिए एक उचित प्रश्न भी नहीं बना सकता कि मैं अभी तक गलत क्या कर रहा हूं। मैं यद्यपि आप सभी को अपडेट करना चाहता हूं और आपकी मदद के लिए धन्यवाद।

वेब के समाधान से एकत्रित समाधान "झुकाव ने अस्वीकृति पर गुजरने का वादा किया"

मेरे लिए, यह परिणाम मतलब नहीं है। इस वादे श्रृंखला के साथ जुड़कर, प्रत्येक तो यह आशय का अर्थ है कि यह डी 1 के सफल समाधान पर निर्भर होगा और परिणाम को श्रृंखला

नहीं। आप जो वर्णन कर रहे हैं वह एक श्रृंखला नहीं है, लेकिन बस सभी कॉलबैक को d1 जोड़ रहा है। फिर भी, अगर आप then साथ कुछ चेन करना चाहते हैं, तो promise2 का नतीजा promise2 के प्रस्ताव पर निर्भर है और कैसे कॉलबैक ने इसे संभाला

डॉक्स राज्य:

कॉलबैक के परिणाम के लिए एक नया वादा देता है

.then विधि आमतौर पर वादे / एक विनिर्देश (या यहां तक ​​कि कड़े प्रमोस / ए + एक ) के मामले में देखा जाता है इसका अर्थ है कि कॉलबैक शेल रिटर्न वादे जो वादा 2 का संकल्प बनने के लिए आत्मसात करेंगे, और यदि कोई सफलता / त्रुटि हैंडलर नहीं है, तो संबंधित परिणाम का promise2 सीधे promise2 तक हो promise2 – ताकि आप केवल promise2 को त्रुटि का प्रचार करने के लिए छोड़ दें।

फिर भी, यदि त्रुटि का संचालन किया जाता है , तो परिणामस्वरूप promise2 निश्चित रूप में देखा जाता है और उस मूल्य से पूरा किया जाएगा। अगर आप ऐसा नहीं करना चाहते हैं, तो आपको त्रुटि को फिर से throw होगा , जैसे कि एक प्रयास-पकड़ खंड में वैकल्पिक रूप से आप हेन्डलर से एक (टू-हो-) अस्वीकृत वादा वापस कर सकते हैं। सुनिश्चित नहीं है कि डोजो कैसे अस्वीकार करने का तरीका है, लेकिन:

 var d1 = d(); var promise1 = d1.promise.then( function(wins) { console.log('promise1 resolved'); return wins;}, function(err) { console.log('promise1 rejected'); throw err;}); var promise2 = promise1.then( function(wins) { console.log('promise2 resolved'); return wins;}, function(err) { console.log('promise2 rejected'); throw err;}); var promise3 = promise2.then( function(wins) { console.log('promise3 resolved'); return wins;}, function(err) { console.log('promise3 rejected'); throw err;}); d1.reject(new Error()); 

जब कोई खुद को नहीं मिला तो बॉब अदरक से एक नीला विजेट कैसे प्राप्त कर सकता है?

वह सक्षम नहीं होना चाहिए यदि कोई त्रुटि संचालकों नहीं हैं, तो वह केवल अदरक से संदेश (((वितरक से जॉन से) को समझ जाएगा कि कोई विगेट्स नहीं छोड़े गए हैं फिर भी, अगर अदरक उस मामले के लिए एक त्रुटि हैंडलर सेट करता है, तो वह अभी भी बॉब को एक विजेट देने के अपने वादे को पूरा कर सकता है जो जॉन या उसके डिस्ट्रीब्यूटर पर छोड़ दिया कोई नीला नहीं है, तो उसे अपने झोंके से एक हरे रंग का दे दे।

मेटापर में अपनी त्रुटि कॉलबैक का अनुवाद करने के लिए, हेन्डलर से return err कीजिए, "यदि कोई विगेट्स नहीं छोड़े गए हैं, तो बस उसे ध्यान दें कि कोई भी नहीं छोड़ा गया है – वांछित विजेट के रूप में उतना ही अच्छा है" कहने जैसा है।

डेटाबेस की स्थिति में, अगर db.query विफल हो गया है, तो यह पहले की गलती समारोह को कॉल करेगा

… जिसका अर्थ होगा कि त्रुटि को वहां संभाला जाता है यदि आप ऐसा नहीं करते हैं, तो बस त्रुटि कॉलबैक को छोड़ दें। बीटीडब्ल्यू, आपकी सफलता कॉलबैक वे जो वे पैदा किए जा रहे हैं, return नहीं return हैं, इसलिए वे काफी बेकार लगते हैं। सही होगा:

 var promise = db.query({parent_id: value}); promise.then(function(query_result) { var first_value = { parent_id: query_result[0].parent_id } var promise = db.put(first_value); return promise.then(function(first_value_result) { var second_value = { reference_to_first_value_id: first_value_result.id } var promise = db.put(second_value); return promise.then(function(second_value_result) { return values_successfully_entered(); }); }); }); 

या, चूंकि आपको पिछले कॉलबैक से परिणाम मानों को एक्सेस करने के लिए क्लोजर की आवश्यकता नहीं है, यहां तक ​​कि:

 db.query({parent_id: value}).then(function(query_result) { return db.put({ parent_id: query_result[0].parent_id }); }).then(function(first_value_result) { return db.put({ reference_to_first_value_id: first_value_result.id }); }.then(values_successfully_entered); 

@ जॉर्डन सबसे पहले टिप्पणीकारों ने उल्लेख किया, स्थगित लिब का उपयोग करते समय, आपका पहला उदाहरण निश्चित रूप से आपके द्वारा अपेक्षित परिणाम उत्पन्न करता है:

 promise1 rejected promise2 rejected promise3 rejected 

दूसरे, भले ही यह आपके द्वारा सुझाए गए उत्पादन का उत्पादन करे, तो यह आपके दूसरे स्निपेट के निष्पादन प्रवाह को प्रभावित नहीं करेगा, जो थोड़ी अलग है, और जैसे:

 promise.then(function(first_value) { console.log('promise1 resolved'); var promise = db.put(first_value); promise.then(function (second_value) { console.log('promise2 resolved'); var promise = db.put(second_value); promise.then( function (wins) { console.log('promise3 resolved'); }, function (err) { console.log('promise3 rejected'); return err; }); }, function (err) { console.log('promise2 rejected'); return err;}); }, function (err) { console.log('promise1 rejected'); return err}); 

और यह कि, पहला वादा अस्वीकार किए जाने के मामले में सिर्फ आउटपुट होगा:

 promise1 rejected 

हालांकि ( सबसे दिलचस्प हिस्सा हो रहा है ) भले ही स्थगित पुस्तकालय निश्चित रूप से 3 x rejected , अन्य वादा पुस्तकालयों में से अधिकांश 1 x rejected, 2 x resolved (जो कि धारणा की ओर जाता है, आपको इसके बजाय कुछ अन्य वायर्ड लाइब्रेरी का उपयोग करके परिणाम प्राप्त होता है) ।

इसके अतिरिक्त भ्रमित होने के कारण, उन अन्य पुस्तकालयों को उनके व्यवहार के साथ अधिक सही है। मुझे समझाने दो।

सिंक्रनाइज़ेशन में "वादा अस्वीकृति" के विश्व समकक्ष को throw । तो शब्दार्थानुसार, सिंक में एसिंक deferred.reject(new Error()) throw new Error() बराबर है आपके उदाहरण में आप अपने सिंक कॉलबैक में त्रुटियों को नहीं फेंक रहे हैं, तो आप उन्हें वापस लौट रहे हैं, इसलिए आप सफलता के प्रवाह पर स्विच करते हैं, एक सफलता मूल्य होने पर त्रुटि। यह सुनिश्चित करने के लिए कि अस्वीकृति आगे बढ़ जाती है, आपको अपनी त्रुटियों को फिर से फेंकने की आवश्यकता है:

 function (err) { console.log('promise1 rejected'); throw err; }); 

तो अब सवाल है, क्यों स्थगित पुस्तकालय ने अस्वीकृति के रूप में त्रुटि वापस ले ली?

इसके लिए कारण, यह है कि आस्थगित कामों में अस्वीकृति थोड़ा अलग है आस्थगित लिब में नियम यह है: जब यह त्रुटि के एक उदाहरण के साथ हल हो जाती है तो वादा अस्वीकार कर दिया जाता है , इसलिए यदि आप deferred.resolve(new Error()) कर देते हैं तो भी। deferred.resolve(new Error()) यह deferred.reject(new Error()) रूप में कार्य करेगा, और यदि आप deferred.reject(notAnError) करने का प्रयास करते हुए यह एक अपवाद फेंकता है, यह वादा केवल त्रुटि के उदाहरण के साथ अस्वीकार कर दिया जा सकता है इससे स्पष्ट हो जाता है कि then कॉलबैक से क्यों त्रुटि आ गई है, वादा

स्थगित तर्क के पीछे कुछ वैध तर्क है, लेकिन फिर भी यह समरूप नहीं है कि जावास्क्रिप्ट में कैसे काम करता है, और इसके कारण यह व्यवहार स्थगित संस्करण v0.7 के साथ बदलाव के लिए निर्धारित है।

संक्षिप्त सारांश:

भ्रम और अनपेक्षित परिणामों से बचने के लिए सिर्फ अच्छे अभ्यास नियमों का पालन करें:

  1. हमेशा एक त्रुटि उदाहरणों के साथ अपने वादों को अस्वीकार करें (सिंक्रनाइज़ेशन दुनिया के नियमों का पालन करें, जहां कोई त्रुटि नहीं है, उसे खराब अभ्यास माना जाता है)।
  2. त्रुटियों को फेंकने से सिंक कॉलबैक से अस्वीकार करें (उन्हें अस्वीकार करने की गारंटी नहीं लौटते हैं)

उपरोक्त मानने के लिए, आपको स्थगित और अन्य लोकप्रिय वायर्ड लाइब्रेरी दोनों में लगातार और अपेक्षित परिणाम मिलेंगे।

उपयोग वादा के प्रत्येक स्तर पर त्रुटियों को लपेट सकते हैं। मैंने TraceError में त्रुटियों को जंजीर दिया है:

 class TraceError extends Error { constructor(message, ...causes) { super(message); const stack = Object.getOwnPropertyDescriptor(this, 'stack'); Object.defineProperty(this, 'stack', { get: () => { const stacktrace = stack.get.call(this); let causeStacktrace = ''; for (const cause of causes) { if (cause.sourceStack) { // trigger lookup causeStacktrace += `\n${cause.sourceStack}`; } else if (cause instanceof Error) { causeStacktrace += `\n${cause.stack}`; } else { try { const json = JSON.stringify(cause, null, 2); causeStacktrace += `\n${json.split('\n').join('\n ')}`; } catch (e) { causeStacktrace += `\n${cause}`; // ignore } } } causeStacktrace = causeStacktrace.split('\n').join('\n '); return stacktrace + causeStacktrace; } }); // access first error Object.defineProperty(this, 'cause', {value: () => causes[0], enumerable: false, writable: false}); // untested; access cause stack with error.causes() Object.defineProperty(this, 'causes', {value: () => causes, enumerable: false, writable: false}); } } 

प्रयोग

 throw new TraceError('Could not set status', srcError, ...otherErrors); 

उत्पादन

कार्य

 TraceError#cause - first error TraceError#causes - list of chained errors