RxJS (Reactive Extensions for JavaScript) একটি শক্তিশালী লাইব্রেরি, যা অ্যাসিঙ্ক্রোনাস ডেটা স্ট্রিম এবং ইভেন্ট পরিচালনার জন্য ব্যবহৃত হয়। এটি ডেটার স্ট্রিমের সাথে কাজ করতে বিভিন্ন Utility Operators প্রদান করে, যা আপনার অ্যাসিঙ্ক্রোনাস স্ট্রিমকে সহজে পরিচালনা করতে সাহায্য করে।
এখানে Observable Lifecycle Management-এর জন্য কিছু গুরুত্বপূর্ণ Utility Operators এবং তাদের ব্যবহার আলোচনা করা হবে।
1. tap() অপারেটর
tap() অপারেটরটি একটি side effect তৈরি করতে ব্যবহৃত হয়, যা Observable এর স্ট্রিমের ওপর কোনো পরিবর্তন ছাড়াই অপারেশন সম্পাদন করে। এটি সাধারণত ডিবাগিং, লগিং বা এক্সটার্নাল প্রক্রিয়া (যেমন, ইউজার ইন্টারফেসের আপডেট বা মেট্রিক সংগ্রহ) করার জন্য ব্যবহৃত হয়, যখন মূল স্ট্রিমের মানে কোনো পরিবর্তন আনতে না হয়।
বৈশিষ্ট্য:
- Side Effect: স্ট্রিমের সাথে কোনো পরিবর্তন ছাড়াই অপারেশন সম্পাদন করতে পারে (যেমন লগিং বা ডিবাগিং)।
- Observable Chain-এ কোন পরিবর্তন আসে না, কেবলমাত্র side effect সম্পাদিত হয়।
উদাহরণ:
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';
const observable = of(1, 2, 3, 4);
observable.pipe(
tap(value => console.log(`Intercepted value: ${value}`)) // Logging the values without modifying the stream
).subscribe(value => console.log(`Received value: ${value}`));
আউটপুট:
Intercepted value: 1
Received value: 1
Intercepted value: 2
Received value: 2
Intercepted value: 3
Received value: 3
Intercepted value: 4
Received value: 4
এখানে, tap() অপারেটরটি স্ট্রিমের মানগুলি লগ করছে, তবে স্ট্রিমের মূল ডেটা পরিবর্তিত হচ্ছে না।
2. finalize() অপারেটর
finalize() অপারেটরটি Observable স্ট্রিমের শেষে কিছু কার্যকলাপ (cleanup) সম্পাদন করার জন্য ব্যবহৃত হয়। এটি Observable lifecycle শেষ হওয়ার পর, অর্থাৎ স্ট্রিমটি সম্পূর্ণ হওয়া অথবা ত্রুটি ঘটার পর কার্যকর হয়। এটি সাধারণত অ্যাসিঙ্ক্রোনাস কাজের পর ক্লিন-আপ বা রিসোর্স ফ্রি করার জন্য ব্যবহার করা হয়।
বৈশিষ্ট্য:
- Cleanup: Observable স্ট্রিমের শেষে ক্লিন-আপ কার্যকলাপ পরিচালনা করতে ব্যবহৃত হয়।
- Completion or Error: স্ট্রিমটি কমপ্লিট অথবা ত্রুটি হলে কার্যকর হয়।
উদাহরণ:
import { of } from 'rxjs';
import { finalize } from 'rxjs/operators';
const observable = of(1, 2, 3);
observable.pipe(
finalize(() => {
console.log('Observable has completed or errored!');
})
).subscribe(
value => console.log(`Received value: ${value}`),
error => console.log(`Error: ${error}`),
() => console.log('Completed')
);
আউটপুট:
Received value: 1
Received value: 2
Received value: 3
Observable has completed or errored!
Completed
এখানে, finalize() অপারেটরটি Observable স্ট্রিম সম্পূর্ণ হওয়ার পর "Observable has completed or errored!" মেসেজটি প্রিন্ট করেছে।
3. delay() অপারেটর
delay() অপারেটরটি Observable স্ট্রিমের মধ্যে নির্দিষ্ট সময়ের বিলম্ব (delay) তৈরি করতে ব্যবহৃত হয়। এটি প্রধানত time-based operations যেমন, টাইমার, ডিলে বা ইন্টারভ্যাল হ্যান্ডলিংয়ের জন্য ব্যবহৃত হয়।
বৈশিষ্ট্য:
- Time Delay: স্ট্রিমে কিছু সময়ের জন্য বিলম্ব তৈরি করে।
- Timed Operations: নির্দিষ্ট সময়ের মধ্যে কোন কাজ সম্পাদন করতে সহায়তা করে।
উদাহরণ:
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
const observable = of('Hello', 'World');
observable.pipe(
delay(1000) // 1 second delay
).subscribe(value => console.log(value));
আউটপুট:
Hello
World
এখানে, delay() অপারেটরটি ১ সেকেন্ড বিলম্বের সাথে আউটপুট দেয়।
4. retry() এবং retryWhen() অপারেটর
retry() এবং retryWhen() অপারেটরগুলি ত্রুটি (error) ঘটলে পুনরায় চেষ্টা করার জন্য ব্যবহৃত হয়। retry() নির্দিষ্ট সংখ্যক বার retry করতে সাহায্য করে, এবং retryWhen() আরও কাস্টম retry লজিক তৈরি করতে সহায়তা করে।
বৈশিষ্ট্য:
- Automatic Retries: ত্রুটি ঘটলে পুনরায় চেষ্টা করে।
- Error Recovery: অ্যাসিঙ্ক্রোনাস স্ট্রিমে error পরিস্থিতি মোকাবেলা করতে সাহায্য করে।
উদাহরণ: retry()
import { of, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
const observable = throwError('Something went wrong');
observable.pipe(
retry(2), // Retry 2 times
catchError(err => {
console.log('Caught error:', err);
return of('Recovered with fallback value');
})
).subscribe({
next: value => console.log('Received:', value),
error: err => console.log('Error:', err),
complete: () => console.log('Completed'),
});
আউটপুট:
Caught error: Something went wrong
Received: Recovered with fallback value
Completed
এখানে, retry(2) অপারেটরটি ত্রুটি হওয়ার পর ২ বার পুনরায় চেষ্টা করেছে এবং তার পরে catchError() ফালব্যাক ভ্যালু প্রদান করেছে।
5. take() এবং takeUntil() অপারেটর
take() এবং takeUntil() অপারেটরগুলি একটি নির্দিষ্ট সংখ্যা বা শর্তে Observable স্ট্রিম থেকে ডেটা নেওয়ার জন্য ব্যবহৃত হয়। take() নির্দিষ্ট সংখ্যা পর্যন্ত ডেটা নেয়, এবং takeUntil() একটি নির্দিষ্ট স্ট্রিমের মান আসা পর্যন্ত ডেটা নেয়।
বৈশিষ্ট্য:
- Limited Subscription: স্ট্রিম থেকে নির্দিষ্ট সংখ্যক বা শর্তে ডেটা গ্রহণ করা।
- Condition-based Stream Termination: নির্দিষ্ট শর্ত পূর্ণ হলে স্ট্রিম বন্ধ করা।
উদাহরণ: take()
import { of } from 'rxjs';
import { take } from 'rxjs/operators';
const observable = of(1, 2, 3, 4, 5);
observable.pipe(
take(3) // Take first 3 values
).subscribe(value => console.log(value));
আউটপুট:
1
2
3
এখানে, take(3) অপারেটরটি প্রথম ৩টি মানই সাবস্ক্রাইবে পাঠিয়েছে।
উদাহরণ: takeUntil()
import { interval, of } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
const observable = interval(1000); // Emits values every second
const notifier = of('Stop'); // Stops the stream when this emits
observable.pipe(
takeUntil(notifier) // Takes values from observable until notifier emits
).subscribe(value => console.log(value));
আউটপুট:
0
1
2
এখানে, takeUntil() যখন notifier Observable থেকে 'Stop' আসে, তখন স্ট্রিম বন্ধ হয়ে যায়।
সারাংশ
RxJS-এ Utility Operators ব্যবহার করে আপনি Observable Lifecycle সহজে ম্যানেজ করতে পারেন। এই অপারেটরগুলির মাধ্যমে আপনি ডেটার স্ট্রিমের lifecycle পরিচালনা, ডিবাগিং, ক্লিন-আপ, পুনরায় চেষ্টা এবং বিলম্ব নিয়ন্ত্রণ করতে পারেন। কয়েকটি গুরুত্বপূর্ণ utility operator এর উদাহরণ:
- tap(): Side effect তৈরি করার জন্য।
- finalize(): স্ট্রিমের শেষের ক্লিন-আপ কাজ।
- delay(): স্ট্রিমে বিলম্ব তৈরি করা।
- retry() এবং retryWhen(): error হলে পুনরায় চেষ্টা করা।
- take() এবং takeUntil(): নির্দিষ্ট সংখ্যক বা শর্ত অনুযায়ী ডেটা নেওয়া।
এই অপারেটরগুলির মাধ্যমে আপনি আপনার Observable স্ট্রিমের জীবনচক্র (Lifecycle) কার্যকরভাবে পরিচালনা করতে পারবেন।
Read more