Answer 1:
অবশ্যই, async/await এবং ডেটা ফেচিং নিয়ে আপনার প্রশ্নগুলোর উপর ভিত্তি করে একটি সহজ বাংলা ব্লগ পোস্ট নিচে দেওয়া হলো।
Async/Await: যেভাবে আধুনিক জাভাস্ক্রিপ্টে ডেটা আনা হয় 🚀
ওয়েব ডেভেলপমেন্টে ডেটা আনা বা পাঠানো (fetching) একটি সাধারণ কাজ। কিন্তু জাভাস্ক্রিপ্ট একই সাথে কেবল একটি কাজ করতে পারে (single-threaded)। তাহলে নেটওয়ার্ক থেকে ডেটা আসতে যে সময় লাগে, সেই সময়ে তো ওয়েবসাইটটি অচল (freeze) হয়ে যাওয়ার কথা! 🤔
এই সমস্যার সমাধান হলো Asynchronous (অ্যাসিঙ্ক্রোনাস) প্রোগ্রামিং। আর async/await হলো এর সবচেয়ে আধুনিক এবং সহজ উপায়। চলুন, আপনার প্রশ্নগুলোর উত্তর জেনে নেওয়া যাক।
async function-এর কাজ কী?
সহজ কথায়, কোনো সাধারণ ফাংশনের আগে async শব্দটি যোগ করলে সেটি একটি বিশেষ ফাংশনে পরিণত হয়। এর দুটি প্রধান বৈশিষ্ট্য হলো:
- Promise রিটার্ন করে: একটি
asyncফাংশন সবসময় একটি Promise রিটার্ন করে। যদি আপনি ফাংশন থেকে সাধারণ কোনো মান (যেমন, একটি সংখ্যা বা স্ট্রিং) রিটার্ন করেন,asyncফাংশন সেটিকে একটি Promise-এর ভেতরে র্যাপ করে পাঠিয়ে দেবে। awaitব্যবহারের সুযোগ দেয়:asyncফাংশনের ভেতরে আপনিawaitকিওয়ার্ডটি ব্যবহার করতে পারবেন, যা অ্যাসিঙ্ক্রোনাস কোডকে সহজভাবে লিখতে সাহায্য করে।
// এই ফাংশনটি একটি Promise রিটার্ন করবে
async function sayHello() {
return "Hello, World!";
}
sayHello().then((message) => console.log(message)); // আউটপুট: Hello, World!এর ভিতরে await fetch লিখলে কী হয়?
যখন একটি async ফাংশনের ভেতরে await fetch(...) লেখা হয়, তখন দারুণ একটি ঘটনা ঘটে।
fetchহলো নেটওয়ার্ক থেকে ডেটা আনার জন্য একটি ব্রাউজার API।fetchকল করার সাথে সাথেই এটি একটি Promise পাঠিয়ে দেয়, কারণ ডেটা আসতে কিছুটা সময় লাগবে।awaitকিওয়ার্ডটিfetch-এর পাঠানো Promise-এর জন্য অপেক্ষা করে। এটি জাভাস্ক্রিপ্ট ইঞ্জিনকে বলে, "এই লাইনে একটু থামো, જ્યાં পর্যন্ত ডেটা না আসে বা কোনো এরর না হয়, সামনে এগিও না।"
সবচেয়ে গুরুত্বপূর্ণ বিষয় হলো, এটি শুধু ওই async ফাংশনটির التنفيذকে থামায়, পুরো ব্রাউজারকে নয়। ফলে ব্যবহারকারী ওয়েবসাইটে অন্য কাজ চালিয়ে যেতে পারে। ডেটা চলে এলে, await Promise থেকে আসল রেসপন্সটি বের করে দেয় এবং ফাংশনটি আবার চলা শুরু করে।
async function getUserData() {
console.log("Fetching data...");
// এখানে কোডটি থেমে যাবে, কিন্তু ব্রাউজার সচল থাকবে
const response = await fetch("https://api.github.com/users/octocat");
const data = await response.json(); // রেসপন্স থেকে JSON ডেটা বের করার জন্যও অপেক্ষা
console.log(data); // ডেটা পাওয়ার পর এটি প্রিন্ট হবে
console.log("Data fetched!");
}কেন ফেচ করার জন্য async/await বা Promise বেশি ব্যবহার হয়?
আগে জাভাস্ক্রিপ্টে অ্যাসিঙ্ক্রোনাস কাজগুলো Callback Function দিয়ে করা হতো। এতে কোড খুব দ্রুতই নোংরা এবং জটিল হয়ে যেত, যা "Callback Hell" বা "Pyramid of Doom" নামে পরিচিত।
async/await এই সমস্যার একটি চমৎকার সমাধান।
- সহজপাঠ্য (Readable):
async/awaitব্যবহার করলে কোড দেখতে সাধারণ, সিঙ্ক্রোনাস (step-by-step) কোডের মতো মনে হয়। ফলে কোড বোঝা এবং ম্যানেজ করা অনেক সহজ হয়। - ত্রুটি ব্যবস্থাপনা (Error Handling):
try...catchব্লক ব্যবহার করে খুব সহজেই এরর হ্যান্ডেল করা যায়, যা Promise-এর.catch()-এর চেয়ে বেশি স্বজ্ঞাত।
✅ async/await দিয়ে:
async function fetchData() {
try {
const response = await fetch("url");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Failed to fetch:", error);
}
}async/await ছাড়া আর কী উপায়ে ডেটা ফেচ করা হয়?
async/await ছাড়াও রিয়েল অ্যাপ্লিকেশনে ডেটা ফেচ করার আরও কিছু জনপ্রিয় উপায় আছে।
-
Promise with
.then()and.catch():async/awaitমূলত Promise-এর উপর তৈরি একটি সহজ সিনট্যাক্স। তাই সরাসরি Promise-এর.then()মেথড ব্যবহার করেও একই কাজ করা যায়। এটি এখনও খুব প্রচলিত।fetch("url") .then((response) => response.json()) .then((data) => { console.log(data); }) .catch((error) => { console.error("Failed to fetch:", error); }); -
লাইব্রেরি ব্যবহার করে (যেমন Axios): অনেক বড় অ্যাপ্লিকেশনে
fetch-এর পরিবর্তে Axios-এর মতো লাইব্রেরি ব্যবহার করা হয়। কারণ এগুলো বিল্ট-ইন অনেক সুবিধা দেয়, যেমন:- স্বয়ংক্রিয়ভাবে JSON ডেটা পার্সিং।
- সহজ এরর হ্যান্ডেলিং।
- অনুরোধ বাতিল (request cancellation) করার সুবিধা।
-
XMLHttpRequest (XHR): 📜 এটি
fetchএবং Promise আসার আগের পুরানো পদ্ধতি। আধুনিক কোডে এর ব্যবহার প্রায় নেই বললেই চলে, তবে পুরানো প্রজেক্টে এটি দেখতে পারেন।
AbortController এবং setTimeout কেন দরকার? 🎮
ধরুন, আপনি একটি বড় ফাইল ডাউনলোড করার জন্য fetch অনুরোধ পাঠালেন। কিন্তু ব্যবহারকারী পৃষ্ঠাটি থেকে চলে গেল অথবা নেটওয়ার্ক খুব স্লো। এই অবস্থায় অনুরোধটি বাতিল করতে না পারলে রিসোর্স নষ্ট হয়।
AbortController এই সমস্যার সমাধান করে। এটি একটি সিগন্যাল তৈরি করে যা দিয়ে চলমান fetch অনুরোধকে যেকোনো মুহূর্তে বাতিল (abort) করা যায়।
setTimeout ব্যবহার করে এই প্রক্রিয়াটিকে আরও শক্তিশালী করা হয়। আমরা setTimeout দিয়ে একটি টাইমার সেট করতে পারি। যদি নির্দিষ্ট সময়ের (যেমন, ১৫ সেকেন্ড) মধ্যে fetch তার কাজ শেষ করতে না পারে, তাহলে setTimeout স্বয়ংক্রিয়ভাবে AbortController-কে বলে দেবে অনুরোধটি বাতিল করে দিতে। একেই "request timeout" বলা হয়, যা একটি ভালো ইউজার এক্সপেরিয়েন্সের জন্য জরুরি।
async function fetchDataWithTimeout() {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 15000); // ১৫ সেকেন্ডের টাইমআউট
try {
const response = await fetch("url", { signal: controller.signal });
const data = await response.json();
console.log(data);
} catch (error) {
if (error.name === "AbortError") {
console.error("Request timed out!");
} else {
console.error("Failed to fetch:", error);
}
} finally {
clearTimeout(timeoutId); // সফল হলে বা এরর হলেও টাইমারটি পরিষ্কার করা উচিত
}
}আশা করি, এই পোস্টটি আপনাকে async/await এবং ডেটা ফেচিংয়ের আধুনিক পদ্ধতিগুলো বুঝতে সাহায্য করেছে!
চমৎকার প্রশ্ন! এটি অ্যাসিঙ্ক্রোনাস জাভাস্ক্রিপ্টের একটি খুবই গুরুত্বপূর্ণ ধারণা। চলুন, আপনার প্রশ্ন দুটি ধাপে ধাপে ভেঙে বুঝি।
১. setTimeout-এর কোড নিচে লেখার পরেও কীভাবে কাজ করে?
এই বিষয়টি বোঝার জন্য জাভাস্ক্রিপ্টের ইভেন্ট লুপ (Event Loop) এবং ওয়েব এপিআই (Web API) কীভাবে কাজ করে তা জানতে হবে।
সহজ ভাষায়:
setTimeout একটি নন-ব্লকিং (non-blocking) ফাংশন। এর মানে হলো, জাভাস্ক্রিপ্ট যখন setTimeout লাইনটি পায়, সে কোডটিকে থামিয়ে দেয় না। বরং, সে এই কাজটি ব্রাউজারের ওয়েব এপিআই-এর কাছে পাঠিয়ে দেয় এবং নিজে পরের লাইনে চলে যায়।
আসুন একটি উদাহরণ দিয়ে পুরো প্রক্রিয়াটি দেখি:
const controller = new AbortController();
// ধাপ ১: টাইমার সেট করা
const timeout = setTimeout(() => controller.abort(), 15000);
// ধাপ ২: Fetch অনুরোধ পাঠানো
const res = await fetch(url, { signal: controller.signal });
// ধাপ ৪ (সফল হলে): টাইমার বাতিল করা
clearTimeout(timeout);কীভাবে এটি কাজ করে:
-
ধাপ ১: টাইমার সেট করা
- কোড যখন
setTimeoutলাইনটি পড়ে, তখন জাভাস্ক্রিপ্ট ব্রাউজারকে বলে: "আমার জন্য একটি ১৫ সেকেন্ডের টাইমার চালু করো। ১৫ সেকেন্ড পার হয়ে গেলে,() => controller.abort()এই ফাংশনটি চালানোর জন্য প্রস্তুত থেকো।" - এই নির্দেশ দেওয়ার সাথে সাথেই জাভাস্ক্রিপ্ট আর অপেক্ষা করে না। সে পরের লাইনে, অর্থাৎ
fetchঅনুরোধ পাঠানোর কাজে চলে যায়। টাইমারটি ব্যাকগ্রাউন্ডে চলতে থাকে।
- কোড যখন
-
ধাপ ২: Fetch অনুরোধ পাঠানো
- এখন
fetchফাংশনটি কল হয় এবং সার্ভার থেকে ডেটা আনার কাজ শুরু করে।awaitথাকার কারণে কোডটি এখানেfetch-এর উত্তরের জন্য অপেক্ষা করে।
- এখন
-
এরপর দুটি ঘটনা ঘটতে পারে:
-
ঘটনা ক (সফল এবং দ্রুত): ধরুন, সার্ভারটি খুব দ্রুত এবং ৫ সেকেন্ডের মধ্যেই উত্তর পাঠিয়ে দিলো।
fetchসফলভাবে শেষ হবে।- কোড পরের লাইনে যাবে এবং
clearTimeout(timeout)실행 করবে। - এই লাইনটি ব্রাউজারকে বলবে: "আমি যে ১৫ সেকেন্ডের টাইমারটি সেট করতে বলেছিলাম, সেটি আর দরকার নেই, ওটা বাতিল করে দাও।"
- ফলে,
controller.abort()ফাংশনটি আর কখনোই কল হবে না।
-
ঘটনা খ (ব্যর্থ বা ধীর): ধরুন, সার্ভারটি খুব ধীর এবং ১৫ সেকেন্ড পার হয়ে গেছে, কিন্তু এখনো কোনো উত্তর আসেনি।
- ব্যাকগ্রাউন্ডে চলতে থাকা টাইমারটির সময় শেষ হয়ে যাবে।
- ব্রাউজার দেখবে যে ১৫ সেকেন্ড হয়ে গেছে, তাই সে
() => controller.abort()ফাংশনটিকে কল করবে। controller.abort()কল হওয়ার সাথে সাথেfetchঅনুরোধটি বাতিল (abort) হয়ে যাবে।fetchএকটিAbortErrorছুড়ে দেবে, যাtry...catchব্লকেরcatchঅংশটি ধরে ফেলবে এবং ব্যবহারকারীকে একটি উপযুক্ত বার্তা দেখাবে।
-
মূল কথা হলো, setTimeout কোডটিকে থামিয়ে না রেখে একটি ভবিষ্যতের কাজ নির্ধারণ করে দেয় এবং মূল কোড তার নিজের গতিতে চলতে থাকে।
২. শুধু normal fetch দিয়ে ডেটা আনলে কী ঘটত?
আপনি ঠিকই ধরেছেন, fetch নিজেও একটি অ্যাসিঙ্ক্রোনাস ফাংশন। শুধু fetch ব্যবহার করলেও ডেটা আনা যায়। কিন্তু AbortController এবং setTimeout ছাড়া ব্যবহার করলে কিছু গুরুত্বপূর্ণ সমস্যা দেখা দেয়, যা একটি ভালো মানের অ্যাপ্লিকেশনে কাম্য নয়।
শুধুমাত্র normal fetch ব্যবহার করলে যে সমস্যাগুলো হতো:
-
কোনো টাইমআউট থাকত না (No Timeout):
- সমস্যা: যদি সার্ভারটি ডাউন থাকে বা নেটওয়ার্ক খুব স্লো হয়, তাহলে
fetchঅনুরোধটি উত্তর না আসা পর্যন্ত অপেক্ষা করতে থাকবে। ব্রাউজারের নিজস্ব একটি ডিফল্ট টাইমআউট থাকে, যা অনেক দীর্ঘ (কয়েক মিনিট)। ফলে, ব্যবহারকারী একটি লোডিং স্ক্রিনের দিকে তাকিয়ে থাকবে এবং বুঝবে না কেন ডেটা আসছে না। এটি একটি খুবই বাজে অভিজ্ঞতা। - সমাধান:
setTimeoutওAbortControllerএকটি নির্দিষ্ট সময় (যেমন ১৫ বা ২০ সেকেন্ড) পর অনুরোধটি বাতিল করে দেয় এবং ব্যবহারকারীকে জানায় যে, "সার্ভার সাড়া দিতে দেরি করছে"।
- সমস্যা: যদি সার্ভারটি ডাউন থাকে বা নেটওয়ার্ক খুব স্লো হয়, তাহলে
-
অনুরোধ বাতিল করার কোনো উপায় থাকত না (No Way to Cancel):
- সমস্যা: ধরুন, ব্যবহারকারী একটি ডেটা লোড হওয়ার জন্য অনুরোধ করলো, কিন্তু অপেক্ষা না করে অন্য পেজে চলে গেল।
normal fetchব্যাকগ্রাউন্ডে চলতেই থাকবে। এটি অপ্রয়োজনে ব্যবহারকারীর ব্যান্ডউইথ এবং ডিভাইসের রিসোর্স নষ্ট করবে। - সমাধান:
AbortControllerদিয়ে আমরা এই অপ্রয়োজনীয় অনুরোধটি বাতিল করে দিতে পারি। যেমন, React-এ একটি কম্পোনেন্ট unmount হওয়ার সময়useEffect-এর cleanup ফাংশনেcontroller.abort()কল করে দিলে রিসোর্স অপচয় রোধ করা যায়।
- সমস্যা: ধরুন, ব্যবহারকারী একটি ডেটা লোড হওয়ার জন্য অনুরোধ করলো, কিন্তু অপেক্ষা না করে অন্য পেজে চলে গেল।
-
ত্রুটি ব্যবস্থাপনা সীমিত থাকত (Limited Error Handling):
- সমস্যা:
normal fetchদিয়ে আপনি শুধু সাধারণ নেটওয়ার্ক এরর (যেমন ইন্টারনেট সংযোগ নেই) ধরতে পারবেন। কিন্তু "সার্ভারটি স্লো" নাকি "সার্ভারটিতে সমস্যা"— এই দুয়ের মধ্যে পার্থক্য করতে পারবেন না। - সমাধান:
AbortControllerব্যবহার করলে,catchব্লকে আপনিerror.name === 'AbortError'চেক করে বুঝতে পারবেন যে অনুরোধটি টাইমআউটের কারণে বাতিল হয়েছে। ফলে আপনি ব্যবহারকারীকে আরও সুনির্দিষ্ট একটি বার্তা দেখাতে পারবেন।
- সমস্যা:
সংক্ষেপে, একটি টেবিলের মাধ্যমে পার্থক্যটি দেখা যাক:
| বৈশিষ্ট্য | Normal fetch | fetch + AbortController + setTimeout |
|---|---|---|
| টাইমআউট | নেই (ব্রাউজারের দীর্ঘ ডিফল্ট টাইমআউট) | আছে (প্রোগ্রামার দ্বারা নিয়ন্ত্রিত) |
| বাতিল করার ক্ষমতা | নেই | আছে (যেকোনো সময় বাতিল করা যায়) |
| ব্যবহারকারীর অভিজ্ঞতা | খারাপ হতে পারে (অসীম অপেক্ষা) | উন্নত (দ্রুত ফিডব্যাক ও নিয়ন্ত্রণ) |
| রিসোর্স ম্যানেজমেন্ট | দুর্বল (অপ্রয়োজনীয় অনুরোধ চলতে থাকে) | উন্নত (রিসোর্স অপচয় রোধ করে) |
তাই বলা যায়, শুধু fetch কাজ চালাবার জন্য যথেষ্ট হলেও, একটি শক্তিশালী, নির্ভরযোগ্য এবং ব্যবহারকারী-বান্ধব অ্যাপ্লিকেশন তৈরির জন্য AbortController এবং setTimeout-এর মতো টুলস অত্যন্ত জরুরি।