फिर से पहले और बाद में पकड़ने का स्थान


103

मुझे .catchएक नेस्टेड वादे में BEFORE और AFTER लगाने के बीच के अंतर को समझने में परेशानी होती है ।

वैकल्पिक 1:

test1Async(10).then((res) => {
  return test2Async(22)
    .then((res) => {
      return test3Async(100);
    }).catch((err) => {
      throw "ERROR AFTER THEN";
    });
}).then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
});

वैकल्पिक 2:

test1Async(10).then((res) => {
   return test2Async(22)
     .catch((err) => {
        throw "ERROR BEFORE THEN";
      })
      .then((res) => {
        return test3Async(100);
      });
  }).then((res) => {
    console.log(res);
  }).catch((err) => {
    console.log(err);
  });

प्रत्येक फ़ंक्शन का व्यवहार निम्नानुसार है, यदि नंबर 2 है तो test1 विफल हो <0जाता है यदि संख्या है > 10और Test3 विफल रहता है यदि संख्या नहीं है 100। इस मामले में test2 केवल विफल हो रहा है।

मैंने चलाने की कोशिश की और test2Async को विफल बनाने के लिए, BEFORE और AFTER दोनों के बाद एक ही तरह से व्यवहार करता है और वह test3Async निष्पादित नहीं कर रहा है। क्या कोई मुझे विभिन्न स्थानों पर कैच देने का मुख्य अंतर समझा सकता है?

प्रत्येक फ़ंक्शन में मैं console.log('Running test X')यह जांचने के लिए कि क्या यह निष्पादित होता है।

यह प्रश्न उठता है कि पिछले धागे के कारण मैंने पोस्ट किया था कि नेस्टेड कॉलबैक को वादे में कैसे बदलें? । मुझे लगता है कि यह एक अलग समस्या है और किसी अन्य विषय को पोस्ट करने के लायक है।


दोनों .then और .catch वादा बदल सकते हैं ... तो मुझे यकीन नहीं है कि गलत समझ कहां से आती है। यदि आप .then से पहले कैच डालते हैं, तो यह अस्वीकार हो जाता है जो .then और thethen के पहले हुआ था। यह चलेगा / .कच के भीतर जो होता है, उसके आधार पर कॉलबैक को विफल करता है, और जब आप उन्हें स्वैप करते हैं तो इसके विपरीत।
केविन बी

क्षमा करें यदि मेरा प्रश्न स्पष्ट नहीं था। लेकिन इस मामले में जैसा कि मैंने कहा, दोनों मामले समान व्यवहार करते हैं इसलिए मैं अंतर नहीं देख सकता। क्या आप बता सकते हैं कि हमने कब BEFORE को पकड़ा और जब हमने इसे बाद में डालने का फैसला किया? इसे लगाने के बाद वास्तव में सहज और आम लगता है। बस यह निश्चित नहीं है कि कभी-कभी हम इसे पहले क्यों डालते हैं
ज़ेंको

यदि वे समान प्रदर्शन करते हैं, तो यह केवल इसलिए है क्योंकि प्रत्येक इस विशिष्ट मामले में परिणाम को बदल नहीं रहा है। या तो एक मामूली परिवर्तन परिणाम को बदल सकता है।
केविन बी

आपका क्या मतलब है "परिणाम बदलना"। क्षमा करें, मैं वास्तव में भ्रमित हूँ हाहा
ज़ैंको

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

जवाबों:


237

तो, मूल रूप से आप पूछ रहे हैं कि इन दोनों के बीच क्या अंतर है (जहां pकुछ पिछले कोड से बनाया गया वादा है):

return p.then(...).catch(...);

तथा

return p.catch(...).then(...);

P के हल होने या अस्वीकार होने पर या तो अंतर होते हैं, लेकिन क्या वे अंतर मायने रखते हैं या नहीं यह इस बात पर निर्भर करता है कि कोड .then()या .catch()हैंडलर अंदर क्या करता है।

जब pहल होता है तो क्या होता है :

पहली योजना में, जब pहल होता है, तो .then()हैंडलर कहा जाता है। यदि वह .then()हैंडलर या तो एक मूल्य लौटाता है या एक और वादा जो अंततः हल हो जाता है, तो .catch()हैंडलर छोड़ दिया जाता है। लेकिन, यदि .then()हैंडलर या तो एक वादे को फेंकता है या वापस करता है, जो अंततः अस्वीकार कर देता है, तो .catch()हैंडलर मूल वादे में दोनों को खारिज कर देगा p, लेकिन .then()हैंडलर में एक त्रुटि भी होती है ।

दूसरी योजना में, जब pहल होता है, तो .then()हैंडलर कहा जाता है। यदि वह .then()हैंडलर या तो एक वादा पूरा करता है या वापस करता है, जो अंततः खारिज कर देता है, तो .catch()हैंडलर उसे पकड़ नहीं सकता है क्योंकि यह श्रृंखला में उसके पहले है।

तो, यह अंतर # 1 है। यदि .catch()हैंडलर AFTER है, तो यह .then()हैंडलर के अंदर त्रुटियों को भी पकड़ सकता है ।

pअस्वीकार होने पर क्या होता है :

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

दूसरी योजना में, यदि वादा pअस्वीकार होता है, तो .catch()हैंडलर को बुलाया जाता है। यदि आप एक सामान्य मान या एक वादा वापस करते हैं जो अंततः .catch()हैंडलर से हल होता है (इस प्रकार "त्रुटि को संभालना"), तो वादा श्रृंखला हल की स्थिति में स्विच हो जाती है और .then()हैंडलर को .catch()बुलाया जाएगा।

तो यह अंतर # 2 है। यदि .catch()हैंडलर BEFORE है, तो यह त्रुटि को संभाल सकता है और .then()हैंडलर को अभी भी कॉल करने की अनुमति दे सकता है।

कब कौन सा उपयोग करें:

पहली योजना का उपयोग करें यदि आप सिर्फ एक .catch()हैंडलर चाहते हैं जो मूल वादे pया .then()हैंडलर में त्रुटियों को पकड़ सकता है और हैंडलर pको छोड़ देना चाहिए .then()

दूसरी योजना का उपयोग करें यदि आप मूल वादे में त्रुटियों को पकड़ने में सक्षम होना चाहते हैं pऔर शायद (शर्तों के आधार पर), वादा श्रृंखला को हल करने के लिए जारी रखने की अनुमति दें, इस प्रकार .then()हैंडलर को निष्पादित करना ।

दूसरा विकल्प

दोनों कॉलबैक का उपयोग करने के लिए एक अन्य विकल्प है जिसे आप निम्न में से पास कर सकते हैं .then():

 p.then(fn1, fn2)

यह गारंटी देता है कि केवल एक fn1या fn2कभी भी बुलाया जाएगा। अगर pठान ले तो कहलाएगा fn1। यदि pअस्वीकार fn2किया जाता है , तो बुलाया जाएगा। परिणाम में कोई परिवर्तन fn1कभी भी fn2बुलाया या इसके विपरीत नहीं हो सकता है। इसलिए, यदि आप पूरी तरह से सुनिश्चित करना चाहते हैं कि आपके दो हैंडलर में से केवल एक को ही बुलाया जाए, भले ही हैंडलर में क्या होता है तो आप इसका उपयोग कर सकते हैं p.then(fn1, fn2)


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

7
@ArneHugo - अच्छा सुझाव। मैंने कहा।
२०

तो, प्रॉमिस चेनिंग के दौरान हम .then .catch .catch .then तरह के परिदृश्य लिख सकते हैं?
कपिल रघुवंशी

@KapilRaghuwanshi, हाँ, आप इसका उपयोग विफलता के मामले में एक डिफ़ॉल्ट मान पारित करने के लिए कर सकते हैं। यानी Promise.reject(new Error("F")).then(x => x).catch(e => {console.log(e); return [1]}).then(console.log)और Promise.resolve([2]).then(x => x).catch(e => [1]).then(console.log)
CervEd

1
@DmitryShvedov - जैसा कि मैंने अनुमान लगाया, यह गलत है .then(this.setState({isModalOpen: false}))। आप फ़ंक्शन के संदर्भ को पारित नहीं कर रहे हैं .then()ताकि कोड में कोड तुरंत निष्पादित हो (वादे को हल करने से पहले)। यह होना चाहिए .then(() => this.setState({isModalOpen: false}))
jfriend00

31

jfriend00 का उत्तर उत्कृष्ट है, लेकिन मुझे लगा कि अनुरूप तुल्यकालिक कोड को जोड़ना एक अच्छा विचार होगा।

return p.then(...).catch(...);

तुल्यकालिक के समान है:

try {
  iMightThrow() // like `p`
  then()
} catch (err) {
  handleCatch()
}

अगर iMightThrow()नहीं फेंका, then()तो बुलाया जाएगा। यदि यह then()फेंकता है (या यदि खुद फेंकता है), तो handleCatch()कहा जाएगा। ध्यान दें कि catchब्लॉक का कोई नियंत्रण नहीं thenहै या नहीं कहा जाता है।

दूसरी ओर,

return p.catch(...).then(...);

तुल्यकालिक के समान है:

try {
  iMightThrow()
} catch (err) {
  handleCatch()
}

then()

इस मामले में, यदि iMightThrow()नहीं फेंकता है, तो then()निष्पादित करेगा। यदि यह फेंक देता है, तो यह handleCatch()तय करना होगा कि then()क्या कहा जाता है, क्योंकि यदि handleCatch()पुनरावृत्ति होती है, तो then()उसे नहीं बुलाया जाएगा, क्योंकि अपवाद को तुरंत फोन करने वाले को फेंक दिया जाएगा। अगर handleCatch()इनायत से मुद्दे को संभाल सकते हैं, तो then()बुलाया जाएगा।


यह अच्छा विवरण है, लेकिन आप अनाथ लपेट सकता है then()एक मेंfinally{...}
tyskr

2
@ 82Tuskers, क्या आप सुनिश्चित हैं? अगर मैं डाल then()में finally{...}, इसे गलत तरीके से बुलाया नहीं किया जाएगा, भले ही handleCatch()फेंकता है? ध्यान रखें कि मेरा लक्ष्य अनुरूप तुल्यकालिक कोड दिखाना था, अपवादों को संभालने के विभिन्न तरीकों का सुझाव नहीं देना
akivajgordon

इसलिए, यदि हम सभी मामलों को संभालना चाहते हैं, लेकिन फिर भी चेन .then () का उपयोग करना सबसे अच्छा होगा। तब (कुछ करें) .catch (लॉग इरेट और अपडेट स्टेट)। तब (अन्य काम करें) .catch (लॉग इरेट करें)। जहां हम हर बिंदु पर पकड़ने का प्रयास करते हैं, लेकिन आगे भी गतिरोध को अंजाम देते रहते हैं?
अन्ना
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.