2016-08-09 13 views
6

हैंडल करना तर्कों को मान्य करना और कार्यों में त्रुटि लौटना आम बात है।जावास्क्रिप्ट कॉलबैक त्रुटि

हालांकि, इस तरह के रूप में जावास्क्रिप्ट कॉलबैक फ़ंक्शन, में:

function myFunction(num, callback) { 
    if (typeof num !== 'number') return callback(new Error('invalid num')) 
    // do something else asynchronously and callback(null, result) 
} 

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

मैं इस मुद्दे पर कुछ सलाह सुनना चाहता हूं। क्या मुझे सावधानीपूर्वक यह मानना ​​चाहिए कि सभी एसिंक्रोनस कॉलबैक तुरंत निष्पादित किए जा सकते हैं? या मुझे सिंक्रोनस चीज़ को एसिंक्रोनस में कनवर्ट करने के लिए setTimeout (..., 0) जैसे कुछ का उपयोग करना चाहिए। या एक बेहतर समाधान है जिसे मैं नहीं जानता। धन्यवाद।

उत्तर

3

एक एपीआई दस्तावेज़ चाहिए कि यह तुल्यकालिक कॉलबैक या तो फोन करेगा (जैसे Array#sort) या असमकालिक (Promise#then की तरह), और फिर हमेशा उस दस्तावेज गारंटी का पालन करना। यह मिश्रण और मैच नहीं होना चाहिए।

तो हाँ, यदि आपके पास ऐसा फ़ंक्शन है जो सामान्य रूप से कॉलबैक को असीमित रूप से कॉल करेगा, तो हमेशा इसे अतुल्यकालिक रूप से कॉल करें, भले ही यह कॉल क्यों कर रहा हो।

jQuery में एक महान उदाहरण था: जब jQuery पहले कहा, "आस्थगित" वस्तुओं, वे कॉलबैक तुल्यकालिक अगर टाल पहले से ही निपटान कर दिया गया था कहेंगे, लेकिन एसिंक्रोनस रूप से अगर यह नहीं किया था। यह बहुत भ्रम और बग का स्रोत था, जो कि ईएस2015 के वादे की गारंटी है कि then और catch कॉलबैक हमेशा असीमित रूप से कहा जाएगा।


संभव और codebase के बाकी के साथ अंतर पर नहीं हैं, तो सरल कॉलबैक बजाय Promises का उपयोग कर देखो। वादे एसिंक्रोनस ऑपरेशंस (और तुल्यकालिक लोगों के साथ बातचीत) के लिए बहुत स्पष्ट, सरल, गारंटीकृत अर्थशास्त्र और composability प्रदान करते हैं।

+0

मैंने अपना डाउनवोट हटा दिया। मुझे लगता है कि जिस तरह से फ़ंक्शन कहा जाता है, उसके सत्यापन के लिए काफी गंभीर है और उत्पादन में ऐसा नहीं होना चाहिए। –

+0

@ पैट्रिक रॉबर्ट्स: मैंने जवाब के उस हिस्से को हटा दिया है, यह वास्तव में प्रश्न के लिए प्रासंगिक नहीं था। मैं आपका मुद्दा देख सकता हूं, हालांकि मैं इसके साथ सहमत नहीं हूं (अभी तक); मुझे इसके बारे में और अधिक सोचने की जरूरत है। मुझे लगता है कि यदि आप एक ES2015 वादा के सेटअप के दौरान फेंक देते हैं ('चलो पी = नया वादा (संकल्प => {नई त्रुटि फेंक दें);))'), यह वादा कन्स्ट्रक्टर द्वारा अस्वीकार कर दिया जाता है, जो आपके समर्थन करता है उस एपीआई के डिजाइन में गए विचार और अनुभव को देखते हुए एक त्रुटि चैनल के पक्ष में तर्क ... –

+0

मेरा दृष्टिकोण भी गलत है। जैसा कि टिप्पणीकार ने मुझे बताया, कॉलस्टैक विचार करने के लिए बहुत महत्वपूर्ण है, खासकर जब आपके फ़ंक्शन का उपयोग करने वाला डेवलपर अनिश्चित काल तक पुनः प्रयास करने का प्रयास करता है, अंततः त्रुटियों के दौरान आपका फ़ंक्शन सिंक्रोनस होता है, जिसके परिणामस्वरूप स्टैक ओवरफ्लो होता है। –

-1

ठीक है, क्योंकि कॉलर उम्मीद करता है कि फ़ंक्शन तुरंत कॉलबैक फ़ंक्शन निष्पादित करने के लिए असीमित हो या कुछ सेकंड में कोई फर्क नहीं पड़ता।

आपको return करने की आवश्यकता नहीं है, क्योंकि आपके पास कॉलबैक फ़ंक्शन है।

+0

मूल्य प्रदान करने के लिए, कार्य को जल्दी से बाहर निकलने के लिए 'वापसी' जगह पर है। –

+0

क्षमा करें, वहां टिप्पणी नहीं देखी गई। –

0

नहीं, तुरंत वापस कॉल करना हानिकारक नहीं है, और वास्तव में जानबूझकर त्रुटि में देरी से समय और उपरांत बर्बाद हो जाता है। हां, किसी त्रुटि के लिए तुरंत वापस कॉल करना बहुत हानिकारक हो सकता है और इसे एक ऐसे फ़ंक्शन के लिए टाला जाना चाहिए जिसे असीमित माना जाता है! (उस पर देखो, एक 180!)

एक डेवलपर के परिप्रेक्ष्य से, इसके बाद सेट अप केवल क्यों किया जा सकता है इसके कई अच्छे कारण हैं। उदाहरण here के लिए:

const server = net.createServer(() => {}).listen(8080); 

server.on('listening',() => {}); 

listening घटना है, जब तक के बाद .listen(8080) शुरू हो जाती है संलग्न नहीं है, क्योंकि घटना स्रोत कॉल से .listen() को लौट गया।इस मामले में, ईवेंट को लागू करने के बाद .listen() निष्पादित होने के बाद सिंक्रनाइज़ करने का प्रयास असफल हो जाएगा। ,

var num = '5'; 

myFunction(num, function callback(err, result) { 
    if (err) { 
    return myFunction(num, callback); 
    } 

    // handle result 
}); 

अब अगर आप callback तुल्यकालिक त्रुटि के साथ, यह नियंत्रण प्रवाह एक stackoverflow में परिणाम होगा:

यहाँ एक और मामले मैं प्रस्तुत करना चाहता हूँ है। हालांकि यह डेवलपर की गलती है, एक स्टैक ओवरफ्लो एक ऐसी क्रिया से होने वाली वास्तव में एक बुरी चीज है जो असीमित होने की उम्मीद है। callback को तुरंत निष्पादित करने के बजाय त्रुटि को पास करने के लिए setImmediate() का उपयोग करने का यह एक फायदा है।

0

आपके एसिंक्रोनस फ़ंक्शन के कॉलर को पता होना चाहिए कि फ़ंक्शन का आविष्कार करने का क्या परिणाम होगा। एक असीमित काम वापस करने के लिए एक मानक है, वादा करता है।

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

function throwingFunction(num) { 
    return new Promise(function (resolve, reject) { 

    if (typeof num !== 'number') throw new Error('invalid num'); 
    // do something else asynchronously and callback(null, result) 
    }; 
} 

function rejectingFunction(num) { 
    return new Promise(function (resolve, reject) { 

    if (typeof num !== 'number') reject(new Error('invalid num')); 
    // do something else asynchronously and callback(null, result) 
    }; 
} 

// Instead of passing the callback, create the promise and provide your callback to the `then` method. 

var resultThrowing = throwingFunction(num) 
    .then(function (result) { console.log(result); }) 
    .catch(function (error) { console.log(error); }); 

var resultRejecting = rejectingFunction(num) 
    .then(function (result) { console.log(result); }) 
    .catch(function (error) { console.log(error); }); 

दोनों पैटर्न के परिणामस्वरूप त्रुटि और लॉग इन हो जाएगा।

यदि आप वादे का उपयोग करते हैं, तो आपके एसिंक्रोनस फ़ंक्शन के कॉलर को फ़ंक्शन के अंदर आपके कार्यान्वयन के बारे में चिंता करने की आवश्यकता नहीं होगी, और आप या तो त्रुटि को सीधे फेंक सकते हैं या वादे को अस्वीकार कर सकते हैं।

संबंधित मुद्दे