क्या मुझे जल्दी समाधान / अस्वीकार करने के बाद वापस जाने की आवश्यकता है?


262

मान लीजिए मेरे पास निम्नलिखित कोड है।

function divide(numerator, denominator) {
 return new Promise((resolve, reject) => {

  if(denominator === 0){
   reject("Cannot divide by 0");
   return; //superfluous?
  }

  resolve(numerator / denominator);

 });
}

यदि मेरा उद्देश्य rejectजल्दी बाहर निकलने के लिए उपयोग करना है , तो क्या मुझे returnतुरंत बाद में आईएनजी की आदत डालनी चाहिए ?


जवाबों:


370

returnउद्देश्य अस्वीकृति के बाद समारोह के निष्पादन को समाप्त, और यह करने के बाद कोड के निष्पादन को रोकने के लिए है।

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {

    if (denominator === 0) {
      reject("Cannot divide by 0");
      return; // The function execution ends here 
    }

    resolve(numerator / denominator);
  });
}

इस मामले में यह resolve(numerator / denominator);निष्पादित करने से रोकता है , जिसकी सख्त आवश्यकता नहीं है। हालांकि, भविष्य में संभावित जाल को रोकने के लिए निष्पादन को समाप्त करना अभी भी बेहतर है। इसके अलावा, अनावश्यक रूप से कोड को रोकने के लिए यह एक अच्छा अभ्यास है।

पृष्ठभूमि

एक वादा 3 राज्यों में से एक में हो सकता है:

  1. लंबित - प्रारंभिक अवस्था। लंबित से हम दूसरे राज्यों में जा सकते हैं
  2. पूरा - सफल ऑपरेशन
  3. अस्वीकृत - विफल संचालन

जब कोई वादा पूरा या खारिज कर दिया जाता है, तो वह इस राज्य में अनिश्चित काल तक (स्थाई) रहेगा। इसलिए, एक पूरा किया हुआ वादा ठुकरा देना या एक ठुकराया हुआ वादा पूरा करना, असर नहीं करेगा।

यह उदाहरण स्निपेट से पता चलता है कि हालांकि वादे को अस्वीकार किए जाने के बाद पूरा किया गया था, यह अस्वीकार कर दिया गया।

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) {
      reject("Cannot divide by 0");
    }

    resolve(numerator / denominator);
  });
}

divide(5,0)
  .then((result) => console.log('result: ', result))
  .catch((error) => console.log('error: ', error));

तो हमें लौटने की आवश्यकता क्यों है?

यद्यपि हम एक सुलझे हुए वादे को नहीं बदल सकते हैं, अस्वीकार या हल करने से बाकी फ़ंक्शन का निष्पादन नहीं होगा। फ़ंक्शन में कोड हो सकता है जो भ्रामक परिणाम पैदा करेगा। उदाहरण के लिए:

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) {
      reject("Cannot divide by 0");
    }
    
    console.log('operation succeeded');

    resolve(numerator / denominator);
  });
}

divide(5, 0)
  .then((result) => console.log('result: ', result))
  .catch((error) => console.log('error: ', error));

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

संकल्प / अस्वीकार के बाद निष्पादन रोकना:

यह मानक JS नियंत्रण प्रवाह सामग्री है।

  • resolve/ के बाद वापसी reject:

  • resolve/ reject- के साथ वापसी / कॉलबैक के वापसी मूल्य को नजरअंदाज कर दिया है के बाद से, हम अस्वीकार / हल बयान वापस करके एक पंक्ति बचा सकते हैं:

  • अगर / किसी अन्य ब्लॉक का उपयोग करना:

मैं एक returnविकल्प का उपयोग करना पसंद करता हूं क्योंकि कोड चापलूसी है।


28
यह देखते हुए कि कोड वास्तव में अलग तरह से व्यवहार नहीं करेगा अगर returnवहाँ है या नहीं, क्योंकि एक बार एक वादा राज्य निर्धारित किया गया है, तो इसे बदला नहीं जा सकता इसलिए कॉलिंग के resolve()बाद कॉलिंग reject()कुछ अतिरिक्त सीपीयू चक्रों का उपयोग करने के अलावा कुछ भी नहीं करेगा। मैं, अपने आप returnको एक कोड स्वच्छता और दक्षता के दृष्टिकोण से उपयोग करूंगा , लेकिन इस विशिष्ट उदाहरण में इसकी आवश्यकता नहीं है।
jfriend00

1
Promise.try(() => { })नए वादे के बजाय उपयोग करने का प्रयास करें और कॉल / समाधान को अस्वीकार करने से बचें। इसके बजाय आप सिर्फ यह लिख सकते हैं कि return denominator === 0 ? throw 'Cannot divide by zero' : numerator / denominator; मैं Promise.tryएक वादे को पूरा करने के लिए एक साधन के रूप में उपयोग करता हूं और साथ ही कोशिश / पकड़ने वाले ब्लॉकों में लिपटे वादों को खत्म करता हूं जो समस्याग्रस्त हैं।
किंगिंगंगो

2
यह जानना अच्छा है, और मुझे पैटर्न पसंद है। हालाँकि, इस समय Promise.try एक स्टेज 0 सुझाव है, इसलिए आप इसे केवल एक शिम के साथ या ब्लूबर्ड या Q जैसे एक वादा पुस्तकालय का उपयोग करके कर सकते हैं।
Ori Drori

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

3
@JakeWilson - बेशक, यह जावास्क्रिप्ट में सिर्फ सामान्य कोड प्रवाह है और वादों से इसका कोई लेना-देना नहीं है। यदि आप फ़ंक्शन को संसाधित कर रहे हैं और वर्तमान कोड पथ में निष्पादित करने के लिए कोई और कोड नहीं चाहते हैं, तो आप एक सम्मिलित करते हैं return
०६:५० पर jfriend00

37

एक सामान्य मुहावरा, जो आपके चाय का प्याला हो सकता है या नहीं हो सकता है, के returnसाथ गठबंधन करना है reject, साथ ही साथ वादे को अस्वीकार करना और फ़ंक्शन से बाहर निकलना है, ताकि फ़ंक्शन सहित शेष कार्य resolveनिष्पादित न हो। यदि आप इस शैली को पसंद करते हैं, तो यह आपके कोड को थोड़ा अधिक कॉम्पैक्ट बना सकता है।

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) return reject("Cannot divide by 0");
                           ^^^^^^^^^^^^^^
    resolve(numerator / denominator);
  });
}

यह ठीक काम करता है क्योंकि वादा निर्माता किसी भी वापसी मूल्य के साथ कुछ भी नहीं करता है, और किसी भी मामले में resolveऔर rejectकुछ भी नहीं लौटाता है।

उसी मुहावरे का उपयोग कॉलबैक शैली के साथ किसी अन्य उत्तर में दिखाया जा सकता है:

function divide(nom, denom, cb){
  if(denom === 0) return cb(Error("Cannot divide by zero"));
                  ^^^^^^^^^
  cb(null, nom / denom);
} 

फिर से, यह ठीक काम करता है क्योंकि कॉल करने वाला व्यक्ति divideइसे कुछ भी वापस करने की उम्मीद नहीं करता है और वापसी मूल्य के साथ कुछ भी नहीं करता है।


6
मुझे ये पसंद नहीं। इससे यह धारणा बनती है कि आप कुछ ऐसा लौटा रहे हैं जो आप वास्तव में नहीं हैं। आप फ़ंक्शन को अस्वीकार कर रहे हैं और फिर फ़ंक्शन निष्पादन को समाप्त करने के लिए रिटर्न का उपयोग कर रहे हैं। उन्हें अलग लाइनों पर रखें, जो आप कर रहे हैं वह केवल लोगों को भ्रमित करेगा। कोड पठनीयता राजा है।
के - एसओ में विषाक्तता बढ़ रही है।

7
@KarlMorrison आप वास्तव में "कुछ" लौटा रहे हैं, एक अस्वीकृत वादा। मुझे लगता है कि आप जिस "धारणा" के बारे में बात कर रहे हैं वह बहुत व्यक्तिगत है। एक rejectस्थिति लौटने में कुछ भी गलत नहीं है
Frondor

5
@Frondor मुझे नहीं लगता कि आप समझ पाए हैं कि मैंने क्या लिखा है। बेशक आप और मैं इसे समझते हैं, एक ही लाइन पर अस्वीकार करते समय कुछ भी नहीं होता है। लेकिन उन डेवलपर्स के बारे में जो एक परियोजना में आने वाले जावास्क्रिप्ट के लिए उपयोग नहीं किए जाते हैं? इस प्रकार की प्रोग्रामिंग से ऐसे लोगों के लिए पठनीयता कम हो जाती है। जावास्क्रिप्ट इको-सिस्टम आज एक गड़बड़ है और इस प्रकार की प्रथाओं को फैलाने वाले लोग केवल इसे बदतर बना देंगे। यह बुरा अभ्यास है।
के - एसओ में विषाक्तता बढ़ रही है।

1
@KarlMorrison व्यक्तिगत राय! = बुरा व्यवहार। यह शायद एक नए जावास्क्रिप्ट डेवलपर को समझने में मदद करेगा कि वापसी के साथ क्या हो रहा है।
टोबी कॉल्क

1
@TobyCaulk यदि लोगों को यह सीखने की जरूरत है कि रिटर्न क्या होता है, तो उन्हें वादे के साथ नहीं खेलना चाहिए, उन्हें बुनियादी प्रोग्रामिंग सीखनी चाहिए।
के - एसओ में विषाक्तता बढ़ रही है।

10

तकनीकी रूप से यहां इसकी आवश्यकता नहीं है 1 - क्योंकि एक वादा हल या अस्वीकार किया जा सकता है , विशेष रूप से और केवल एक बार। पहला वादा परिणाम जीतता है और हर बाद के परिणाम को अनदेखा किया जाता है। यह नोड-शैली कॉलबैक से अलग है।

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

उचित समय पर वापस लौटना (या "अन्य" मामले को निष्पादित करने से बचने के लिए सशर्त का उपयोग करना) एक अमान्य स्थिति में गलती से चल रहे कोड या अवांछित साइड-इफेक्ट प्रदर्शन की संभावना को कम करता है; और जैसे कि यह कोड को 'अनपेक्षित रूप से तोड़ने' के लिए कम प्रवण बनाता है।


1 यह तकनीकी रूप से उत्तर इस तथ्य पर भी टिका है कि इस मामले में "वापसी" के बाद का कोड, क्या इसे छोड़ दिया जाना चाहिए, परिणाम नहीं होगा। जावास्क्रिप्ट खुशी से शून्य से विभाजित होगा और + इन्फिनिटी / -इनफिनिटी या NaN पर वापस लौटेगा।


अच्छा फुटनोट !!
हांकाका

9

यदि आप किसी समाधान / अस्वीकार के बाद "वापस" नहीं करते हैं, तो आपके द्वारा इसे रोकने के लिए खराब चीजों (जैसे पृष्ठ पुनर्निर्देशित) के बाद हो सकता है। स्रोत: मैं इस में भाग गया।


6
उदाहरण के लिए +1। मेरे पास एक मुद्दा था जहां मेरा कार्यक्रम 100+ अमान्य डेटाबेस प्रश्न बना देगा और मैं यह पता नहीं लगा सका कि क्यों। पता चला कि मैंने अस्वीकार के बाद "वापसी" नहीं की। यह एक छोटी सी गलती है लेकिन मैंने अपना सबक सीखा।
एडमइनऑकुलस

8

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

ध्यान दें कि returnकॉलगर्ल्स में भी बहुत जल्दी आम है:

function divide(nom, denom, cb){
     if(denom === 0){
         cb(Error("Cannot divide by zero");
         return; // unlike with promises, missing the return here is a mistake
     }
     cb(null, nom / denom); // this will divide by zero. Since it's a callback.
} 

इसलिए, जबकि वादों में यह अच्छा अभ्यास है, कॉलबैक के साथ इसकी आवश्यकता होती है । आपके कोड के बारे में कुछ नोट:

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

4

कई मामलों में मापदंडों को अलग-अलग मान्य करना संभव है और तुरंत Promise.reject (कारण) के साथ एक अस्वीकार किए गए वादे को वापस करें ।

function divide2(numerator, denominator) {
  if (denominator === 0) {
    return Promise.reject("Cannot divide by 0");
  }
  
  return new Promise((resolve, reject) => {
    resolve(numerator / denominator);
  });
}


divide2(4, 0).then((result) => console.log(result), (error) => console.log(error));

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