Lesson ১১৬ মিনিট পড়া

এরর হ্যান্ডলিং (Error Handling)

যখন কোনো কিছু উল্টোপাল্টা হবে (এবং তা হবেই), তখন সমস্যাটি আপনাকে ধরশায়ী করার আগেই আপনি সেটির সমাধান করে ফেলুন

কেন এরর বা ভুল হয় (এবং কেন এটি স্বাভাবিক) (Why Errors Happen (And Why That's OK))

প্রোগ্রামিংয়ে এরর বা ভুল হওয়াটা খুবই স্বাভাবিক একটি ব্যাপার। কখনো ব্যবহারকারী হয়তো অপ্রত্যাশিত কিছু টাইপ করে বসলো, কখনো সার্ভার কাজ করা বন্ধ করে দিলো, অথবা হয়তো কোথাও কোনো ফাইলই খুঁজে পাওয়া গেল না। ভালো কোড কখনোই শতভাগ ভুলমুক্ত হয় না — বরং এটি ভালোভাবে সব ভুলগুলোকে সামাল দেয়।

এরর হ্যান্ডলিং বা ভুল সামাল দেওয়ার ব্যাপারটিকে অনেকটা ট্রাপিজ (trapeze) খেলাতে জালের ব্যবহারের মতো ভাবতে পারেন। অ্যাক্রোব্যাট (আপনার কোড) অনেক উঁচুতে দারুণ সব চমক দেখায়, আর জাল (এরর হ্যান্ডলিং) তারা পড়ে গেলে নিচে থেকে ধরে ফেলে বা রক্ষা করে। এই নিরাপত্তা জাল না থাকলে, একটিমাত্র ভুলের কারণে পুরো খেলাই ভেস্তে যেতে পারে।

জাভাস্ক্রিপ্টে বেশ কয়েকটি নিজস্ব বা বিল্ট-ইন (built-in) এরর টাইপ রয়েছে:

  • TypeError — এমন কোনো কাজ করা যা কোনো নির্দিষ্ট ভ্যালুর টাইপ সমর্থন করে না (যেমন null.toString() কল করা)
  • ReferenceError — এমন কোনো ভ্যারিয়েবল ব্যবহার করা যার আসলেই কোনো অস্তিত্ব নেই
  • SyntaxError — এমন কোনো কোড লেখা যা জাভাস্ক্রিপ্ট বুঝতে বা পার্স (parse) করতে পারে না
  • RangeError — নির্ধারিত সীমার বাইরে থাকা কোনো সংখ্যা হলে
  • URIError — ভুল URI এনকোডিং হলে
Click chart to zoom
try/catch/finally এর কন্ট্রোল ফ্লো (Control flow): catch ব্লকটি কেবলমাত্র এরর ছুঁড়ে দেওয়া হলেই রান করে, তবে finally ব্লক যেকোনো পরিস্থিতিতেই রান করে থাকে।

Try / Catch / Finally

// Basic try/catch
try {
let data = JSON.parse("not valid json");
console.log(data);
} catch (error) {
console.log("Caught an error!");
console.log(error.name); // "SyntaxError"
console.log(error.message); // "Unexpected token 'o'..."
}
// finally — always runs, error or not
function readFile(name) {
console.log(`Opening ${name}...`);
try {
if (name === "missing.txt") {
throw new Error("File not found!");
}
console.log(`Reading ${name}... done!`);
return "file contents";
} catch (error) {
console.log(`Error: ${error.message}`);
return null;
} finally {
console.log(`Closing ${name}. (always runs)`);
}
}
readFile("data.txt");
console.log("---");
readFile("missing.txt");
Output
Caught an error!
SyntaxError
Unexpected token 'o', "not valid json" is not valid JSON
Opening data.txt...
Reading data.txt... done!
Closing data.txt. (always runs)
---
Opening missing.txt...
Error: File not found!
Closing missing.txt. (always runs)

নিজের মতো করে এরর ছোঁড়া (Throwing Your Own Errors)

আপনি শুধু জাভাস্ক্রিপ্টের বিল্ট-ইন এররগুলোই ধরতে বা ক্যাচ (catch) করতে পারবেন এমনটা নয় — আপনি চাইলে নিজের মতো করেও এরর ছুঁড়তে (throw) পারেন। আপনার কোডে কোনো সমস্যা হলে তা বোঝানোর জন্য throw ব্যবহার করুন। এটিকে অনেকটা কোথাও আগুন লাগলে অ্যালার্ম বাজানোর সাথে তুলনা করা যায়।

আপনি চাইলে যেকোনো কিছু ছুঁড়তে পারেন (যেমন একটি স্ট্রিং, বা একটি সংখ্যা), তবে সবচেয়ে ভালো উপায় হলো একটি Error অবজেক্ট ছোঁড়া। কারণ এতে একটি স্ট্যাক ট্রেস (stack trace) থাকে — যা ঠিক কোন জায়গা থেকে এররের সৃষ্টি হয়েছে, তার একটি পরিষ্কার ধারণা দেয়।

নিজেদের তৈরি এরর এবং ভ্যালিডেশন (Custom Errors & Validation)

// Throwing errors for validation
function divide(a, b) {
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("Both arguments must be numbers");
}
if (b === 0) {
throw new RangeError("Cannot divide by zero");
}
return a / b;
}
try {
console.log(divide(10, 2)); // 5
console.log(divide(10, 0)); // throws!
} catch (e) {
console.log(`${e.name}: ${e.message}`);
}
// Custom error class
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
function createUser(name, age) {
if (!name) throw new ValidationError("name", "Name is required");
if (age < 0) throw new ValidationError("age", "Age cannot be negative");
return { name, age };
}
try {
createUser("", 25);
} catch (e) {
if (e instanceof ValidationError) {
console.log(`Validation failed on '${e.field}': ${e.message}`);
} else {
throw e; // re-throw unexpected errors
}
}
Output
5
RangeError: Cannot divide by zero
Validation failed on 'name': Name is required

এরর সামলানোর কিছু সাধারণ উপায় বা প্যাটার্ন (Error Handling Patterns)

বাস্তবে কাজ করার সময় আপনি প্রায়ই কোডের এই ধরনের প্যাটার্নগুলো দেখতে পাবেন:

  • ক্যাচ করে সমাধান করা (Catch and recover) — এররটিকে সামাল দিন এবং বিকল্প কোনো উপায় বা ফলব্যাকের (fallback) মাধ্যমে কাজ চালিয়ে যান
  • ক্যাচ করা এবং লগ করা (Catch and log) — ত্রুটি বা ডিবাগিং (debugging) খোঁজার সুবিধার জন্য এররটি লগ করুন, কিন্তু অ্যাপের কাজ চলতে দিন
  • ক্যাচ করা এবং পুনরায় ছোঁড়া (Catch and re-throw) — কেবল আপনার জানা এররগুলো ক্যাচ করুন এবং বাকিগুলোকে আবার ছুঁড়ে দিন
  • গার্ড ক্লজ বা Guard clauses — সমস্যাগুলো এররে পরিণত হওয়ার আগেই if স্টেটমেন্ট ব্যবহার করে সেগুলো পরীক্ষা করে নিন

সহজ কথায় মনে রাখবেন: যেসব কোড বাইরের কোনো মাধ্যমের সাথে যোগাযোগ করে (যেমন নেটওয়ার্ক রিকোয়েস্ট, ফাইলের কাজ, JSON পার্সিং, ব্যবহারকারীর ইনপুট) সেসব ক্ষেত্রে try/catch ব্যবহার করুন। তবে নিজের লেখা লজিকের ক্ষেত্রে, গার্ড ক্লজ এবং ভ্যালিডেশন ব্যবহার করাই উত্তম।

রিয়েল-ওয়ার্ল্ড বা বাস্তব কাজের প্যাটার্ন: নিরাপদ JSON পার্সিং

// A reusable safe parser
function safeJsonParse(text, fallback = null) {
try {
return JSON.parse(text);
} catch {
return fallback;
}
}
// Works perfectly with valid JSON
let data = safeJsonParse('{"name": "Laboni", "level": 5}');
console.log(data); // { name: "Laboni", level: 5 }
// Returns fallback for invalid JSON instead of crashing
let bad = safeJsonParse("not json", { name: "Unknown" });
console.log(bad); // { name: "Unknown" }
// Guard clause pattern — validate early, fail fast
function processOrder(order) {
if (!order) throw new Error("Order is required");
if (!order.items?.length) throw new Error("Order must have items");
if (order.total < 0) throw new Error("Total cannot be negative");
// If we get here, we know the data is good!
console.log(`Processing order: ${order.items.length} items, $${order.total}`);
}
try {
processOrder({ items: ["book", "pen"], total: 24.99 });
processOrder({ items: [], total: 0 });
} catch (e) {
console.log(`Failed: ${e.message}`);
}
Output
{ name: "Laboni", level: 5 }
{ name: "Unknown"
Processing order: 2 items, $24.99
Failed: Order must have items
Note: কখনোই ফাঁকা বা এম্পটি ক্যাচ (empty catch) ব্লক ব্যবহার করবেন না: catch (e) { }। এটিকে এরর "গিলে ফেলা বা সম্পূর্ণ এড়িয়ে যাওয়া" বলা হয়, যা ডিবাগিংয়ের সময় পরিস্থিতিকে আরও দুর্বিষহ করে তোলে, কারণ এই সমস্যাগুলো ভেতরে ভেতরেই চলতে থাকে। তাই অন্ততপক্ষে এররটিকে লগ করে রাখুন: catch (e) { console.error(e); }। আপনার এই ছোট একটি কাজের জন্য ভবিষ্যতের আপনি বর্তমান আপনাকে ধন্যবাদ জানাবে।
চ্যালেঞ্জ

ছোট কুইজ

'finally' ব্লক কখন রান করে?

পড়া চালিয়ে যান

DOM ManipulationClasses & OOP