दिन 18: Errors, try…catch और Debugging
✅ आज आप सीखेंगे
- Error messages और stack traces शांति से पढ़ना
- आम error types: TypeError, ReferenceError, SyntaxError, RangeError
- try…catch…finally और इसे कब (न) लें
- Custom errors throw करना और guard clauses से जल्दी validate
- console, breakpoints, watch और debugger statement से debug
🏢 असली दुनिया में
असली support call: “मेरे phone पर checkout button कुछ नहीं करता।” Customer को कोई error नहीं दिखती, developer इसे दोहरा नहीं पाता, और orders खोते हैं। Professional developers लगभग आधा समय debugging में लगाते हैं। हुनर सारे bugs से बचना नहीं – उन्हें जल्दी ढूँढना और सलीक़े से fail होना है ताकि customer को जमे page की जगह उपयोगी message दिखे।
Errors पढ़ना
const tests = [
() => undefinedVariable + 1, // ReferenceError
() => null.name, // TypeError
() => (42).toUpperCase(), // TypeError
() => new Array(-1), // RangeError
() => JSON.parse('{bad json}'), // SyntaxError (at runtime, from JSON)
];
for (const t of tests) {
try { t(); } catch (err) { console.log(`${err.name}: ${err.message}`); }
}| Error | आमतौर पर मतलब | आम इलाज |
|---|---|---|
| ReferenceError: x is not defined | Typo या scope से बाहर variable | Spelling, declare करें, scope देखें |
| TypeError: Cannot read properties of null/undefined | Element या data ग़ायब | Selector, defer देखें, ?. और guards लें |
| TypeError: x is not a function | ग़लत नाम, या value वह नहीं जो आप सोचते हैं | console.log(typeof x) |
| SyntaxError | टूटा code या JSON | Line/column देखें, छूटे ) } , |
| RangeError | सीमा से बाहर number / अनंत recursion | Loop और recursion की शर्तें देखें |
| Uncaught (in promise) | बिना catch वाला rejected promise | await के चारों ओर try/catch (Day 20) |
पहली line message है, अगली line बताती है कहाँ हुआ (file:line:column)। DevTools में उस पर click करके ठीक line पर जाएँ। नीचे की lines बताती हैं उस function को किसने बुलाया।
try…catch…finally
function loadSavedCart(json) {
try {
const cart = JSON.parse(json); // may throw
console.log('Loaded', cart.items.length, 'items');
return cart;
} catch (err) {
console.log('Could not read the saved cart →', err.name);
return { items: [] }; // recover with a safe default
} finally {
console.log('finally: runs either way (hide the loader, close the file…)');
}
}
loadSavedCart('{"items":[{"id":1}]}');
loadSavedCart('{corrupted');try…catch का बुरा उपयोग
- “बस यूँ ही” पूरे app को लपेटना
- catch (e) {} – errors चुपचाप निगलना
- null जाँचने की जगह इसका उपयोग
- ठीक करने लायक bugs छिपाना
अच्छा उपयोग ⭐
- बाहरी कारणों से fail होने वाले code के चारों ओर: JSON, storage, network
- Default या साफ़ message से संभलना
- बाद में ठीक करने लायक detail log
- जो न संभाल सकें उसे दोबारा throw
Custom errors throw करना और guard clauses
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
function createOrder({ name, phone, qty }) {
// guard clauses: check bad input first, exit early, keep the happy path flat
if (!name || name.trim().length < 2) throw new ValidationError('name', 'Name is too short');
if (!/^[6-9]\d{9}$/.test(phone)) throw new ValidationError('phone', 'Invalid mobile number');
if (!(qty > 0 && qty <= 50)) throw new ValidationError('qty', 'Quantity must be 0–50 kg');
return { id: 'SS' + 1042, name, phone, qty };
}
for (const input of [{ name: 'Aarti', phone: '9829012345', qty: 2 }, { name: 'Aarti', phone: '12345', qty: 2 }, { name: 'A', phone: '9829012345', qty: 2 }]) {
try {
console.log('✅', createOrder(input).id);
} catch (err) {
if (err instanceof ValidationError) console.log(`⚠️ ${err.field}: ${err.message}`);
else throw err; // unknown problem → do not hide it
}
}console.log से आगे
const order = { id: 1042, items: [{ name: 'Ghewar', qty: 2 }], total: 1300 };
console.log('plain:', order);
console.warn('⚠️ low stock for Ghewar'); // yellow in DevTools
console.error('❌ payment failed for order', order.id);
console.table(order.items);
console.group('Order 1042');
console.log('customer: Aarti');
console.log('total: ₹' + order.total);
console.groupEnd();
console.time('loop');
let s = 0; for (let i = 0; i < 1e6; i++) s += i;
console.timeEnd('loop');
console.assert(order.total > 0, 'total must be positive'); // prints only if false
console.count('render'); console.count('render');Breakpoints से debugging
- 1Bug दोहराएँ और ठीक-ठीक steps लिखें
- 2DevTools → Sources → अपनी file खोलें (Ctrl+P)
- 3Line number पर click करके breakpoint (या code में debugger;)
- 4Action चलाएँ – execution वहीं रुकता है
- 5Variables पर hover, Scope और Watch panels में असली values
- 6Step over (F10), into (F11), out (Shift+F11); resume (F8)
- 7मिल गया? ठीक करें, फिर test या guard जोड़ें ताकि दोबारा न आए
| Tool | कब |
|---|---|
| Conditional breakpoint | Line पर right-click → सिर्फ़ qty > 50 पर रुकें |
| Event listener breakpoints | File जाने बिना किसी click या submit पर रुकें |
| DOM breakpoints | Elements → right-click → Break on → subtree modifications |
| Network tab | Requests, status codes और responses (Day 20) |
| Remote debugging | chrome://inspect से USB पर असली Android phone debug |
सलीक़े से fail: global error handling
<button id="ok">Working button</button>
<button id="bad">Buggy button</button>
<div id="toast" role="alert" hidden style="margin-top:10px;padding:10px 14px;border-radius:10px;background:#fee2e2;color:#7f1d1d"></div>
<script>
// Last line of defence: show a friendly message and report the error
window.addEventListener('error', (event) => {
const toast = document.querySelector('#toast');
toast.textContent = 'Sorry, something went wrong. Please try again or call +91 98290 12345.';
toast.hidden = false;
console.error('Reported to developers:', event.message, 'at line', event.lineno);
// in production: send to a logging service (Sentry, your own API) here
});
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled promise:', event.reason);
});
document.querySelector('#ok').addEventListener('click', () => alert('Order button works ✅'));
document.querySelector('#bad').addEventListener('click', () => {
const cart = null;
return cart.items.length; // 💥 TypeError on purpose
});
</script>🏅 आज के Job Skills
Practice tasks
🏋️ Practice – ख़ुद करें
Solution देखें
function safeDivide(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') throw new TypeError('Numbers only');
if (b === 0) throw new RangeError('Cannot divide by zero');
return Math.round(a / b * 100) / 100;
}
for (const [a, b] of [[10, 4], [5, 0], ['5', 1]]) {
try { console.log(`${a} / ${b} =`, safeDivide(a, b)); }
catch (err) { console.log(`${err.name}: ${err.message}`); }
}const total = items.reduce((s, i) => s + i.price * i.qty) “[object Object]…” देता है। समझाएँ और ठीक करें।Solution देखें
const items = [{ price: 900, qty: 2 }, { price: 500, qty: 1 }];
// Without a start value, s starts as the FIRST OBJECT, so object + number → string
const wrong = items.reduce((s, i) => s + i.price * i.qty);
const right = items.reduce((s, i) => s + i.price * i.qty, 0);
console.log(wrong);
console.log(right);Quick quiz
🧠 Quick Quiz – ख़ुद को जाँचें
Interview corner
💼 Interview Corner
सिर्फ़ production में mobile पर होने वाला bug कैसे debug करेंगे?
Details लें (device, browser, steps), stack traces के लिए error logging/monitoring देखें, DevTools device mode और remote debugging (chrome://inspect) से दोहराएँ, network failures और feature support जाँचें, संदिग्ध code के आसपास logging जोड़ें, फिर ठीक करके regression test या guard जोड़ें।
try…catch कब लें?
उन operations के चारों ओर जो आपके नियंत्रण से बाहर कारणों से fail हो सकते हैं – parsing, storage, network, third-party code – जहाँ आप संभल सकें या उपयोगी message दिखा सकें। Validation की जगह या programming errors चुप कराने के लिए नहीं।
सारांश
- Message और stack की पहली line पढ़ें; 5 आम error types सीखें।
- बाहरी विफलताओं के चारों ओर try…catch…finally; संभलें या दोबारा throw।
- Custom errors + guard clauses समस्याएँ साफ़ करते हैं।
- console methods, breakpoints और global handlers bugs ढूँढते और रोकते हैं।
Day 19: asynchronous JavaScript – event loop, timers, callbacks और promises।
