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
-এর মতো টুলস অত্যন্ত জরুরি।