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()`** ব্যবহার করবেন। এটি কোনো এরর আসলে পুরো পাইপলাইন ক্র্যাশ করায় না, বরং প্রতিটি প্রমিজের কাস্টম স্ট্যাটাস অবজেক্ট রিটার্ন করে।