वादों के लिए एंटिथेन (सफलता, असफल) कब माना जाता है?


188

मैंने ब्लूबर्ड वादा एफएक्यू पर एक नज़र डाली , जिसमें यह उल्लेख किया गया है कि .then(success, fail)यह एक एंटीपैटर्न है । मैं कोशिश और पकड़ के रूप में इसके स्पष्टीकरण को काफी नहीं समझता। इसके बाद क्या गलत है?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

ऐसा लगता है कि उदाहरण निम्नलिखित तरीके से सही तरीके से सुझाव दे रहा है।

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

क्या फर्क पड़ता है?


1
then().catch()अधिक पठनीय है, क्योंकि आपको अल्पविराम की तलाश करने की आवश्यकता नहीं है और जांच यह है कि सफलता या असफल शाखा के लिए यह कॉलबैक है।
क्रिज़िस्तोफ़ सफजानोवस्की

7
@ केविनबी: इसमें बहुत अंतर है, उत्तरों की जांच करें
बरगी

12
@KrzysztofSafjanowski - 'बेहतर लग रहा है' तर्क से तबाह। पूरा गलत!
एंड्री पोपोव

6
नोट: जब आप उपयोग कर रहे हैं .catch, तो आप यह नहीं जानते कि कौन सा कदम समस्या का कारण बना - अंतिम thenया कहीं और वादा प्रतिज्ञा के अंदर । तो इसका अपना नुकसान है।
13:15 बजे महत्वपूर्ण-टी

2
मैं हमेशा वादे के लिए फ़ंक्शन नाम जोड़ता हूं। तब () इसे पठनीय बनाने के लिए some_promise_call() .then(function fulfilled(res) { logger.log(res) }, function rejected(err) { logger.log(err) })
पैरामन्स किया जाता है

जवाबों:


215

क्या फर्क पड़ता है?

.then()कॉल एक वादा है कि मामले में कॉलबैक एक त्रुटि फेंकता अस्वीकार कर दिया जाएगा वापस आ जाएगी। इसका मतलब है, जब आपकी सफलता loggerविफल हो जाती है, तो त्रुटि निम्नलिखित .catch()कॉलबैक को पारित की जाएगी , लेकिन failकॉलबैक के साथ नहीं जो साथ जाती है success

यहाँ एक नियंत्रण प्रवाह आरेख है:

दो तर्कों के साथ नियंत्रण प्रवाह आरेख नियंत्रण प्रवाह आरेख तो श्रृंखला को पकड़ने

इसे समकालिक कोड में व्यक्त करने के लिए:

// some_promise_call().then(logger.log, logger.log)
then: {
    try {
        var results = some_call();
    } catch(e) {
        logger.log(e);
        break then;
    } // else
        logger.log(results);
}

दूसरा log(जो पहले तर्क की तरह है .then()) केवल उस मामले में निष्पादित किया जाएगा जब कोई अपवाद नहीं हुआ। लेबल ब्लॉक और breakस्टेटमेंट थोड़ा अजीब लगता है, यह वास्तव में अजगर के try-except-elseलिए क्या है (अनुशंसित पढ़ने!)।

// some_promise_call().then(logger.log).catch(logger.log)
try {
    var results = some_call();
    logger.log(results);
} catch(e) {
    logger.log(e);
}

catchलकड़हारा भी सफलता लकड़हारा कॉल से अपवादों को संभाल लेंगे।

अंतर के लिए इतना।

मैं कोशिश और पकड़ के रूप में इसके स्पष्टीकरण को काफी नहीं समझता

तर्क यह है कि आमतौर पर आप प्रसंस्करण के हर चरण में त्रुटियों को पकड़ना चाहते हैं, और यह कि आप इसे जंजीरों में इस्तेमाल नहीं करें। उम्मीद यह है कि आपके पास केवल एक अंतिम हैंडलर है जो सभी त्रुटियों को संभालता है - जबकि, जब आप "एंटीपैटर्न" का उपयोग करते हैं, तो कुछ कॉलबैक में त्रुटियों को संभाला नहीं जाता है।

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


इसके बाद क्या गलत है?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

कि आपको अपना कॉलबैक दोहराना था। आप बल्कि चाहते हैं

some_promise_call()
   .catch(function(e) {
       return e; // it's OK, we'll just log it
   })
   .done(function(res) {
       logger.log(res);
   });

आप इसके .finally()लिए उपयोग करने पर भी विचार कर सकते हैं ।


7
यह सबसे उपयोगी व्याख्या है जिसे मैंने कुछ दिनों में पढ़ा है (और मैंने बहुत पढ़ा है)। मैं समझा नहीं सकता कि मैं कितना आभारी हूँ! :) मुझे लगता है कि आपको दोनों के बीच के अंतर को अधिक तनाव देना चाहिए, जो सफलता के कार्य के अंदर भी त्रुटियों.catch को पकड़ लेगा .. व्यक्तिगत रूप से, मुझे यह बहुत गलत लगता है क्योंकि आप एक त्रुटि-प्रवेश बिंदु के साथ समाप्त होते हैं, जिससे कई त्रुटियां हो सकती हैं कई क्रियाएं, लेकिन यह मेरी समस्या है। वैसे भी - जानकारी के लिए धन्यवाद! क्या आपके पास कुछ ऑनलाइन संचार उपकरण नहीं हैं जिन्हें आप साझा करना चाहते हैं इसलिए मैं कुछ चीजें और पूछ सकता हूं? : पी
एंड्री पोपोव

2
मुझे उम्मीद है कि यह आपको यहां कुछ और उत्थान दे रहा है। निश्चित रूप से Promiseइस साइट पर एक महत्वपूर्ण मैकेनिक के सर्वोत्तम स्पष्टीकरण में से एक है ।
पैट्रिक रॉबर्ट्स

2
.done()यह मानक का हिस्सा नहीं है, क्या यह है? कम से कम MDN उस विधि को सूचीबद्ध नहीं करता है। यह मददगार होगा।
यज्ञ

1
@ygoe वास्तव में। doneएक ब्लूबर्ड चीज़ है जिसे मूल रूप से then+ अनहेल्ड-रिजेक्शन डिटेक्शन द्वारा हटा दिया गया था ।
बरगी

1
एक colorblind से सिर्फ एक नोट: आरेख कोई मतलब नहीं है :)
Benny K

37

दोनों काफी समान नहीं हैं। अंतर यह है कि पहला उदाहरण आपके successहैंडलर में फेंके गए अपवाद को नहीं पकड़ेगा । इसलिए यदि आपकी विधि को कभी भी हल किए गए वादे वापस करने चाहिए, जैसा कि अक्सर होता है, तो आपको एक अनुगामी catchहैंडलर (या thenखाली successपैरामीटर के साथ एक और ) की आवश्यकता होती है। निश्चित रूप से, यह हो सकता है कि आपका thenहैंडलर ऐसा कुछ भी न करे जो संभावित रूप से विफल हो, जिस स्थिति में 2-पैरामीटर का उपयोग thenकरना ठीक हो सकता है।

लेकिन मेरा मानना ​​है कि आपके द्वारा जोड़ा गया पाठ का वह बिंदु जो thenअतुल्यकालिक चरणों की एक श्रृंखला को चेन करने की क्षमता में अधिकतर उपयोगी बनाम कॉलबैक है, और जब आप वास्तव में ऐसा करते हैं, तो thenसूक्ष्मता के 2-पैरामीटर रूप में अपेक्षित रूप से व्यवहार नहीं किया जाता है। , उपरोक्त कारण से। मिड-चेन का उपयोग करने पर यह विशेष रूप से प्रतिरूप है।

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


18

दोनों के फायदे और नुकसान को देखकर हम एक परिकलित अनुमान लगा सकते हैं जो स्थिति के लिए उपयुक्त है। वादों को लागू करने के लिए ये दो मुख्य दृष्टिकोण हैं। दोनों में इसके प्लसस और माइनस हैं

कैच अप्रोच

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

लाभ

  1. सभी त्रुटियों को एक पकड़ ब्लॉक द्वारा नियंत्रित किया जाता है।
  2. यहां तक ​​कि तत्कालीन ब्लॉक में किसी भी अपवाद को पकड़ता है।
  3. कई सफलता कॉलबैक की चेनिंग

नुकसान

  1. पीछा करने के मामले में विभिन्न त्रुटि संदेश दिखाना मुश्किल हो जाता है।

सफलता / त्रुटि दृष्टिकोण

some_promise_call()
.then(function success(res) { logger.log(res) },
      function error(err) { logger.log(err) })

लाभ

  1. आपको ठीक दानेदार त्रुटि नियंत्रण मिलता है।
  2. आपके पास त्रुटियों की विभिन्न श्रेणियों जैसे डीबी त्रुटि, 500 त्रुटि आदि के लिए सामान्य त्रुटि हैंडलिंग फ़ंक्शन हो सकता है।

Disavantages

  1. catchयदि आपको सफलता कॉलबैक द्वारा फेंकी गई हैंडलर त्रुटियों की इच्छा है, तो भी आपको एक और की आवश्यकता होगी

किसी ऐसे व्यक्ति के लिए जिसे सिर्फ एक लॉग फ़ाइल का उपयोग करके उत्पादन के मुद्दों को डीबग करना होगा मैं सफलता / त्रुटि दृष्टिकोण को पसंद करता हूं क्योंकि यह एक कारण त्रुटि श्रृंखला बनाने की क्षमता देता है जिसे आप ऐप की निकास सीमाओं पर लॉग इन कर सकते हैं।
शेन रोवेट

सवाल। मैं कहता हूं कि मैं एक एसिंक्स कॉल करता हूं जो कुछ चीजों में से एक करता है: 1) सफलतापूर्वक (2xx स्टेटस), 2) रिटर्न (असफल 4xx या 5xx कोड) लेकिन प्रति सेकंड अस्वीकृत नहीं होता है, 3) या बिल्कुल नहीं लौटता है ( इंटरनेट कनेक्शन नीचे है)। केस # 1 के लिए, तब .then में सफलता कॉलबैक हिट है। केस # 2 के लिए, .then में त्रुटि कॉलबैक हिट है। केस # 3 के लिए, .चेक कहा जाता है। यह सही विश्लेषण है, है ना? केस # 2 सबसे मुश्किल है bc तकनीकी रूप से एक 4xx या 5xx एक अस्वीकृति नहीं है, यह अभी भी सफलतापूर्वक रिटर्न करता है। इस प्रकार, हमें इसे .then के भीतर संभालने की आवश्यकता है। .... क्या मेरी समझ सही है?
बेंजामिन हॉफमैन

"केस # 2 के लिए, .then में त्रुटि कॉलबैक हिट है। केस # 3 के लिए, .catch कहा जाता है। यह सही विश्लेषण है, है ना?" - यह है कि कैसे काम करता है
aWebDeveloper

2

सरल व्याख्या:

ES2018 में

जब पकड़ने की विधि को तर्क पर रोक के साथ बुलाया जाता है, तो निम्नलिखित कदम उठाए जाते हैं:

  1. इस मूल्य का वादा करते हैं।
  2. वापसी ? आह्वान (वादा, "फिर", «अपरिभाषित, onRejected»)।

इसका मतलब है कि:

promise.then(f1).catch(f2)

बराबरी

promise.then(f1).then(undefiend, f2)

1

उपयोग .then().catch()करने से आप प्रोमिस चेनिंग को सक्षम कर सकते हैं जो वर्कफ़्लो को पूरा करने के लिए आवश्यक है। आपको डेटाबेस से कुछ जानकारी पढ़ने की आवश्यकता हो सकती है फिर आप इसे एक async एपीआई में पारित करना चाहते हैं फिर आप प्रतिक्रिया में हेरफेर करना चाहते हैं। आप डेटाबेस में प्रतिक्रिया को पीछे धकेलना चाह सकते हैं। अपनी अवधारणा के साथ इन सभी वर्कफ़्लो को संभालना संभव नहीं है, लेकिन प्रबंधन के लिए बहुत कठिन है। बेहतर समाधान वह होगा then().then().then().then().catch()जो केवल एक बार पकड़ने में सभी त्रुटियों को प्राप्त करता है और आपको कोड की स्थिरता बनाए रखने देता है ।


0

उपयोग करना then()और catch()वादे पर चेन की सफलता और विफलता हैंडलर की मदद करता है। catch()द्वारा किए गए वादे पर काम करता है then()। यह संभालता है,

  1. अगर वादा खारिज कर दिया गया। तस्वीर में # 3 देखें
  2. यदि पंक्ति 4 से 7 के बीच नीचे () की सफलता हैंडलर में त्रुटि हुई है। तस्वीर में # 2.a देखें (विफलता कॉलबैक then()इसे नहीं संभालती है।)
  3. यदि त्रुटि तब के विफलता हैंडलर में हुई (), पंक्ति संख्या 8 नीचे। तस्वीर में # 3. बी देखें।

1. let promiseRef: Promise = this. aTimetakingTask (false); 2. promiseRef 3. .then( 4. (result) => { 5. /* successfully, resolved promise. 6. Work on data here */ 7. }, 8. (error) => console.log(error) 9. ) 10. .catch( (e) => { 11. /* successfully, resolved promise. 12. Work on data here */ 13. });

यहां छवि विवरण दर्ज करें

नोट : कई बार, विफलता हैंडलर को परिभाषित नहीं किया जा सकता है अगर catch()पहले से ही लिखा गया हो। संपादित करें: reject()लागू में परिणाम catch()केवल तभी में त्रुटि हैंडलर then()है नहीं परिभाषित किया। तस्वीर में # 3 नोटिस करें catch()। इसे तब लागू किया जाता है जब लाइन # 8 और 9 में हैंडलर को परिभाषित नहीं किया जाता है।

यह समझ में आता है क्योंकि then()यदि कॉलबैक इसकी देखभाल कर रहा है तो लौटाए गए वादे में त्रुटि नहीं है।


नंबर 3 से catchकॉलबैक तक का तीर गलत लगता है।
बरगी

धन्यवाद! तब () में परिभाषित एक त्रुटि कॉलबैक के साथ, यह कोडित नहीं है (कोड स्निपेट में लाइन # 8 और # 9)। # 3 दो में से एक तीर मारता है। यह समझ में आता है क्योंकि तब तक लौटाए गए वादे () में त्रुटि नहीं होती है यदि कॉलबैक इसका ध्यान रख रहा है। जवाब संपादित किया!
वेंकापी

-1

शब्दों के बजाय, अच्छा उदाहरण। निम्नलिखित कोड (यदि पहला वादा हल हुआ):

Promise.resolve()
.then
(
  () => { throw new Error('Error occurs'); },
  err => console.log('This error is caught:', err)
);

के समान है:

Promise.resolve()
.catch
(
  err => console.log('This error is caught:', err)
)
.then
(
  () => { throw new Error('Error occurs'); }
)

लेकिन खारिज किए गए पहले वादे के साथ, यह समान नहीं है:

Promise.reject()
.then
(
  () => { throw new Error('Error occurs'); },
  err => console.log('This error is caught:', err)
);

Promise.reject()
.catch
(
  err => console.log('This error is caught:', err)
)
.then
(
  () => { throw new Error('Error occurs'); }
)

4
इसका कोई मतलब नहीं है, क्या आप इस उत्तर को हटा सकते हैं? यह सही उत्तर से भ्रामक और विचलित करने वाला है।
एंडी रे

@AndyRay, यह वास्तविक अनुप्रयोग में कोई मतलब नहीं है, लेकिन यह वादों के काम को समझने के लिए समझ में आता है।
ktretyak
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.