बेंजामिन का जवाब इस मुद्दे को हल करने के लिए एक महान अमूर्तता प्रदान करता है, लेकिन मैं कम सार समाधान की उम्मीद कर रहा था। इस मुद्दे को हल करने का स्पष्ट तरीका केवल .catch
आंतरिक वादों पर कॉल करना है, और उनके कॉलबैक से त्रुटि वापस करना है।
let a = new Promise((res, rej) => res('Resolved!')),
b = new Promise((res, rej) => rej('Rejected!')),
c = a.catch(e => { console.log('"a" failed.'); return e; }),
d = b.catch(e => { console.log('"b" failed.'); return e; });
Promise.all([c, d])
.then(result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
.catch(err => console.log('Catch', err));
Promise.all([a.catch(e => e), b.catch(e => e)])
.then(result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
.catch(err => console.log('Catch', err));
इसे एक कदम आगे बढ़ाते हुए, आप एक सामान्य कैच हैंडलर लिख सकते हैं जो इस तरह दिखता है:
const catchHandler = error => ({ payload: error, resolved: false });
तो आप कर सकते हैं
> Promise.all([a, b].map(promise => promise.catch(catchHandler))
.then(results => console.log(results))
.catch(() => console.log('Promise.all failed'))
< [ 'Resolved!', { payload: Promise, resolved: false } ]
इसके साथ समस्या यह है कि पकड़े गए मूल्यों में गैर-पकड़े गए मूल्यों की तुलना में एक अलग इंटरफ़ेस होगा, इसलिए इसे साफ करने के लिए आप कुछ कर सकते हैं:
const successHandler = result => ({ payload: result, resolved: true });
तो अब आप यह कर सकते हैं:
> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
.then(results => console.log(results.filter(result => result.resolved))
.catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]
फिर इसे DRY में रखने के लिए, आपको बेंजामिन का जवाब मिलेगा:
const reflect = promise => promise
.then(successHandler)
.catch(catchHander)
अब यह कैसा दिखता है
> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
.then(results => console.log(results.filter(result => result.resolved))
.catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]
दूसरे समाधान के लाभ यह हैं कि इसका सार और DRY। नकारात्मक पक्ष यह है कि आपके पास अधिक कोड है, और आपको चीजों को लगातार बनाने के लिए अपने सभी वादों को प्रतिबिंबित करना याद रखना होगा।
मैं स्पष्ट और KISS, लेकिन वास्तव में कम मजबूत के रूप में मेरे समाधान की विशेषताएँ हैं। इंटरफ़ेस गारंटी नहीं देता है कि आप वास्तव में जानते हैं कि वादा सफल हुआ या विफल।
उदाहरण के लिए आपके पास यह हो सकता है:
const a = Promise.resolve(new Error('Not beaking, just bad'));
const b = Promise.reject(new Error('This actually didnt work'));
यह द्वारा पकड़ा नहीं जाएगा a.catch
, तो
> Promise.all([a, b].map(promise => promise.catch(e => e))
.then(results => console.log(results))
< [ Error, Error ]
यह बताने का कोई तरीका नहीं है कि कौन सा घातक था और कौन सा नहीं था। यदि यह महत्वपूर्ण है तो आप इसे लागू करना चाहते हैं और इंटरफ़ेस को ट्रैक करते हैं कि यह सफल था या नहीं (जो किreflect
करता है)।
यदि आप केवल त्रुटियों को सावधानीपूर्वक संभालना चाहते हैं, तो आप त्रुटियों को अपरिभाषित मान सकते हैं:
> Promise.all([a.catch(() => undefined), b.catch(() => undefined)])
.then((results) => console.log('Known values: ', results.filter(x => typeof x !== 'undefined')))
< [ 'Resolved!' ]
मेरे मामले में, मुझे त्रुटि जानने की आवश्यकता नहीं है या यह कैसे विफल हुआ - मुझे सिर्फ यह ध्यान है कि मेरे पास मूल्य है या नहीं। मैं विशिष्ट त्रुटि लॉग करने के बारे में वादा चिंता उत्पन्न करता है कि समारोह में दूँगा।
const apiMethod = () => fetch()
.catch(error => {
console.log(error.message);
throw error;
});
इस तरह, शेष एप्लिकेशन इसकी त्रुटि को अनदेखा कर सकता है यदि वह चाहे, और इसे अपरिभाषित मान के रूप में मान सकता है।
मैं अपने उच्च स्तर के कार्यों क्यों अपनी निर्भरता में विफल रहा है पर विवरण के बारे में सुरक्षित रूप से और न चिंता विफल चाहते हैं, और मुझे लगता है कि दुविधा यह करना है जब मैं भी सूखने के लिए KISS पसंद करते हैं - जो अंततः यही कारण है कि मैं का उपयोग नहीं करने का विकल्प चुना reflect
।