অ্যাঙ্গুলারে Observable হলো অনেকটা একটি “পাইপলাইন” বা “অপেক্ষার খাতা”-র মতো। এটি ইভেন্ট ড্রিভেন প্রোগ্রামিংয়ের একটি অংশ।
সহজ করে ৩টি পয়েন্টে বুঝে নাও:
১. এটি একটি অলস (Lazy) মেথড
তুমি যখন deleteCategory(id) মেথডটি কল করো, অ্যাঙ্গুলার সাথে সাথে এপিআই রিকোয়েস্ট পাঠায় না। সে শুধু একটি Observable অবজেক্ট বা “প্ল্যান” রিটার্ন করে।
- Observable মানে হলো: “আমি তোমাকে কথা দিচ্ছি, ভবিষ্যতে যখন তুমি আমাকে কল (Subscribe) করবে, তখন আমি এপিআই থেকে ডাটা এনে দেব।”
২. কেন Observable<void>?
তুমি ডটনেটে NoContent() রিটার্ন করেছ, যা কোনো ডাটা পাঠায় না। তাই অ্যাঙ্গুলার সাইডে তুমি বলে দিচ্ছ <void>। অর্থাৎ:
- Observable: ভবিষ্যতে কিছু একটা ঘটবে।
<void>: কিন্তু ভেতর থেকে কোনো ডাটা (Object) আসবে না।
৩. সাবস্ক্রাইব (Subscribe) না করলে কাজ হবে না
Observable এর সবচেয়ে বড় বৈশিষ্ট্য হলো—যতক্ষণ না কেউ এটি .subscribe() করছে, ততক্ষণ এটি কোনো রিকোয়েস্ট ফায়ার করে না।
উদাহরণ:
TypeScript
// ১. এটা লিখলে এপিআই রিকোয়েস্ট যাবে না (শুধু একটা পাইপ তৈরি হলো)
const deleteAction = this.categoryService.deleteCategory('123');
// ২. এটা লিখলেই কেবল সার্ভারে ডিলিট রিকোয়েস্ট যাবে
deleteAction.subscribe(() => {
console.log('এখন ডিলিট হয়েছে!');
});
কেন আমরা Promise এর বদলে Observable ব্যবহার করি?
তুমি হয়তো জাভাস্ক্রিপ্টে Promise দেখেছ। Observable তার চেয়ে শক্তিশালী কারণ:
- Cancelable: রিকোয়েস্ট মাঝপথে থামিয়ে দেওয়া যায়।
- Operators: তুমি ডাটা আসার আগে সেটাকে ফিল্টার বা ম্যাপ করতে পারো।
- Stream: এটি একবার ডাটা এনেই শান্ত হয় না, চাইলে বারবার ডাটা পাঠাতে পারে (যেমন রিয়েল-টাইম চ্যাট)।
তোমার জন্য ছোট সারকথা:
Observable হলো একটি অপেক্ষা করার মাধ্যম। তোমার সার্ভিস বলছে, “আমি একটা ডিলিট রিকোয়েস্টের অর্ডার নিলাম, তুমি যখনই রেডি (Subscribe) হবে, আমি তখনই সার্ভারে পাঠাবো।”
তুমি কি এখন তোমার ডিলিট ফাংশনটি কম্পোনেন্ট থেকে কল করে দেখেছ? সাবস্ক্রাইব না করলে কিন্তু ক্যাটাগরি ডিলিট হবে না!
httpResource সিগন্যাল
তোমার এইচটিএমএল কোডটি বেশ সুন্দর এবং গোছানো। এখানে তুমি অ্যাঙ্গুলারের লেটেস্ট কন্ট্রোল ফ্লো (@if, @for, @empty) ব্যবহার করেছো, যা কোডকে অনেক বেশি ক্লিন করে দিয়েছে।
তোমার প্রশ্নগুলোর উত্তর নিচে বিস্তারিত আলোচনা করা হলো:
১. isLoading এবং isError কি httpResource এর সিগন্যাল?
হ্যাঁ, একদম তাই। যখন তুমি তোমার টাইপস্ক্রিপ্ট ফাইলে এভাবে লেখো:
TypeScript
categoryListRef = this.categoryServices.getAllCategories(); // এটা একটা Resource
isLoading = this.categoryListRef.isLoading; // Resource থেকে আসা সিগন্যাল
isError = this.categoryListRef.error; // Resource থেকে আসা সিগন্যাল
categoryList = this.categoryListRef.value; // Resource থেকে আসা ডাটা সিগন্যাল
এখানে isLoading এবং isError আলাদা কোনো ভেরিয়েবল নয়, এগুলো httpResource-এর ভেতরে থাকা বিল্ট-ইন Writable Signals।
isLoading(): যখনই এপিআই কল শুরু হয়, অ্যাঙ্গুলার অটোমেটিক এটাকেtrueকরে দেয়। ডাটা চলে আসলে বা এরর হলে এটি আবারfalseহয়ে যায়। তাই তোমাকে ম্যানুয়ালি লোডিং হ্যান্ডেল করতে হচ্ছে না।isError(): যদি এপিআই কোনো কারণে ফেইল করে (যেমন: ৪0৪ বা ৫00 এরর), তবে এই সিগন্যালটি একটি এরর অবজেক্ট পায় এবং তোমার এইচটিএমএল-এ ওই এরর মেসেজটি অটোমেটিক শো করে।
২. reload() করলে আসলে কী হবে?
তুমি যখন ডিলিট করার পর this.categoryListRef.reload() কল করবে, তখন মূলত ৩টি ঘটনা ঘটবে:
- নতুন এপিআই রিকোয়েস্ট: অ্যাঙ্গুলার বুঝবে যে তোমার ডাটা “পুরানো” হয়ে গেছে। সে সাথে সাথে তোমার
getAllCategories()এপিআই-তে আবার একটা রিকোয়েস্ট পাঠাবে। - অটোমেটিক স্টেট চেঞ্জ: * কল করার সাথে সাথে তোমার
isLoading()আবারtrueহয়ে যাবে। ফলে ইউজার টেবিলের জায়গায় আবার স্পিনার দেখতে পাবে (যদি তুমি@if (isLoading())ব্যবহার করো)।- ডাটা আসার পর
isLoading()আবারfalseহবে এবং টেবিলটি নতুন ডাটা দিয়ে আপডেট হবে।
- ডাটা আসার পর
- ইউজার এক্সপেরিয়েন্স: ইউজার ডিলিট বাটনে ক্লিক করার পর টেবিলটি একবার রিফ্রেশ হবে এবং ডিলিট হওয়া ক্যাটাগরিটা উধাও হয়ে যাবে। এতে ইউজার নিশ্চিত হবে যে কাজটা হয়েছে।
কেন reload() ব্যবহার করা this.categoryListRef = ... এর চেয়ে ভালো?
যদি তুমি পুরো categoryListRef-কে আবার অ্যাসাইন করো, তবে অ্যাঙ্গুলার পুরো মেমোরিতে নতুন একটা অবজেক্ট তৈরি করবে। কিন্তু reload() করলে সে আগের অবজেক্টটাকেই শুধু রিফ্রেশ করে। এটি পারফরম্যান্সের জন্য ভালো এবং কোড দেখতেও ক্লিন লাগে।
সারকথা: তোমার কোড এখন একদম প্রো-লেভেলে আছে। httpResource-এর কারণে তোমাকে ম্যানুয়ালি কোনো Subscription বা Loading Variable ম্যানেজ করতে হচ্ছে না—সব অ্যাঙ্গুলার একাই সামলাচ্ছে!
এখন কি ডিলিট করার পর ডাটা অটোমেটিক লিস্ট থেকে চলে যাচ্ছে? (যদি ব্রাউজারে চেক করে থাকো)।