JavaScript & Software Engineering

Mastering Asynchronous JavaScript: Beyond Async/Await and Promise.all

জাভাস্ক্রিপ্ট হলো একটি সিঙ্গেল-থ্রেডেড (Single-threaded) ল্যাঙ্গুয়েজ, অর্থাৎ এটি একবারে একটির বেশি কাজ করতে পারে না। কিন্তু নেটওয়ার্ক রিকোয়েস্ট পাঠানো, ডাটাবেজ অপারেশন বা ফাইল রিড-রাইট করার মতো ভারী কাজগুলো যদি মেইন থ্রেডকে ব্লক করে রাখে, তবে পুরো অ্যাপ হ্যাং হয়ে যাবে। এই সমস্যার সমাধান দেয় **Asynchronous JS**।

আধুনিক জাভাস্ক্রিপ্টে আমরা `async/await` ব্যবহার করে কোডকে খুব সুন্দর ও পঠনযোগ্য করি। তবে অনেক ডেভলপার অজান্তেই `await` কি-ওয়ার্ডটি এমনভাবে ব্যবহার করেন যা প্যারালাল এক্সিকিউশনকে ব্যাহত করে কোডকে স্লো করে দেয়। আজ আমরা শিখবো কীভাবে জাভাস্ক্রিপ্টের ফুল কনকারেন্সি পাওয়ার আনলক করা যায়।

১. সাধারণ ভুল: সিরিয়াল অ্যাওয়েট ট্র্যাপ (The Sequential Await Trap)

নিচের কোড ব্লকটি লক্ষ্য করুন, যেখানে দুটি সম্পূর্ণ স্বাধীন এপিআই থেকে ডেটা ফেচ করা হচ্ছে কিন্তু কোডটি অপ্রয়োজনীয়ভাবে ডবল সময় নিচ্ছে:

// ❌ ব্যাক-টু-ব্যাক সিরিয়াল এক্সিকিউশন (স্লো প্রসেস)
async function fetchBadMetrics() {
    const userData = await fetch('/api/user'); // ২ সেকেন্ড লাগবে
    const analyticsData = await fetch('/api/analytics'); // আরও ২ সেকেন্ড লাগবে (টোটাল ৪ সেকেন্ড)
    return { userData, analyticsData };
}

ধাপ ২: প্রফেশনাল সমাধান - Promise Concurrency পাইপলাইন

যেহেতু দুটি রিকোয়েস্ট একে অপরের ওপর নির্ভরশীল নয়, তাই আমরা এদেরকে একসাথে ব্রাউজার বা নোড ভি-৮ (V8 Node Engine) ব্যাকগ্রাউন্ড থ্রেডে ফায়ার করতে পারি **`Promise.all`** বা আধুনিক **`Promise.allSettled`** এর মাধ্যমে:

//  প্যারালাল এক্সিকিউশন মেকানিজম (ফাস্ট প্রসেস)
async function fetchOptimizedMetrics() {
    try {
        // দুটি প্রমিজ একসাথে ফায়ার করা হলো ব্যাকগ্রাউন্ডে
        const [userResponse, analyticsResponse] = await Promise.all([
            fetch('/api/user'),
            fetch('/api/analytics')
        ]);
        
        const userData = await userResponse.json();
        const analyticsData = await analyticsResponse.json();
        
        return { userData, analyticsData }; // টোটাল সময় লাগবে মাত্র ২ সেকেন্ড!
    } catch (error) {
        console.error("Asynchronous pipeline failure:", error);
    }
}

অ্যাডভান্সড ইঞ্জিনিয়ারিং টিপস: যদি আপনার প্রজেক্টে এমন লজিক থাকে যেখানে যেকোনো একটি এপিআই কল ফেইল হলেও বাকিগুলোর সাকসেস ডেটা প্রয়োজন, তবে `Promise.all` এর পরিবর্তে **`Promise.allSettled()`** ব্যবহার করবেন। এটি কোনো এরর আসলে পুরো পাইপলাইন ক্র্যাশ করায় না, বরং প্রতিটি প্রমিজের কাস্টম স্ট্যাটাস অবজেক্ট রিটার্ন করে।