জাভাস্ক্রিপ্টের অ্যাসিঙ্ক ইটারেটর হেল্পারগুলিতে এরর হ্যান্ডলিং এর একটি সম্পূর্ণ নির্দেশিকা, যেখানে এরর প্রোপাগেশন কৌশল, বাস্তব উদাহরণ এবং স্থিতিস্থাপক স্ট্রিমিং অ্যাপ্লিকেশন তৈরির সেরা অনুশীলনগুলি আলোচনা করা হয়েছে।
জাভাস্ক্রিপ্ট অ্যাসিঙ্ক ইটারেটর হেল্পার এরর প্রোপাগেশন: শক্তিশালী অ্যাপ্লিকেশনের জন্য স্ট্রিম এরর হ্যান্ডলিং
আধুনিক জাভাস্ক্রিপ্ট ডেভেলপমেন্টে অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং একটি অপরিহার্য অংশ হয়ে উঠেছে, বিশেষ করে যখন ডেটা স্ট্রিমের সাথে কাজ করা হয়। অ্যাসিঙ্ক ইটারেটর এবং অ্যাসিঙ্ক জেনারেটর ফাংশনগুলি ডেটা অ্যাসিঙ্ক্রোনাসভাবে, অর্থাৎ একটির পর একটি উপাদান করে প্রসেস করার জন্য শক্তিশালী টুল সরবরাহ করে। তবে, শক্তিশালী এবং নির্ভরযোগ্য অ্যাপ্লিকেশন তৈরির জন্য এই কাঠামোগুলির মধ্যে ত্রুটিগুলি সুন্দরভাবে পরিচালনা করা অত্যন্ত গুরুত্বপূর্ণ। এই বিস্তারিত নির্দেশিকাটি জাভাস্ক্রিপ্টের অ্যাসিঙ্ক ইটারেটর হেল্পারগুলিতে এরর প্রোপাগেশনের জটিলতাগুলি অন্বেষণ করে এবং স্ট্রিমিং অ্যাপ্লিকেশনগুলিতে কার্যকরভাবে ত্রুটি পরিচালনার জন্য বাস্তব উদাহরণ এবং সেরা অনুশীলনগুলি সরবরাহ করে।
অ্যাসিঙ্ক ইটারেটর এবং অ্যাসিঙ্ক জেনারেটর ফাংশন বোঝা
এরর হ্যান্ডলিং-এ যাওয়ার আগে, আসুন অ্যাসিঙ্ক ইটারেটর এবং অ্যাসিঙ্ক জেনারেটর ফাংশনগুলির মৌলিক ধারণাগুলি সংক্ষেপে পর্যালোচনা করি।
অ্যাসিঙ্ক ইটারেটর
একটি অ্যাসিঙ্ক ইটারেটর হলো একটি অবজেক্ট যা একটি next() মেথড সরবরাহ করে, যা একটি প্রমিস রিটার্ন করে যা value এবং done বৈশিষ্ট্য সহ একটি অবজেক্টে রিজলভ হয়। value বৈশিষ্ট্যটি ক্রমের পরবর্তী মান ধারণ করে এবং done বৈশিষ্ট্যটি নির্দেশ করে যে ইটারেটরটি সম্পন্ন হয়েছে কিনা।
উদাহরণ:
async function* createAsyncIterator(data) {
for (const item of data) {
await new Promise(resolve => setTimeout(resolve, 50)); // Simulate asynchronous operation
yield item;
}
}
const asyncIterator = createAsyncIterator([1, 2, 3]);
async function consumeIterator() {
let result = await asyncIterator.next();
while (!result.done) {
console.log(result.value);
result = await asyncIterator.next();
}
}
consumeIterator(); // Output: 1, 2, 3 (with delays)
অ্যাসিঙ্ক জেনারেটর ফাংশন
একটি অ্যাসিঙ্ক জেনারেটর ফাংশন একটি বিশেষ ধরনের ফাংশন যা একটি অ্যাসিঙ্ক ইটারেটর রিটার্ন করে। এটি অ্যাসিঙ্ক্রোনাসভাবে মান তৈরি করতে yield কীওয়ার্ড ব্যবহার করে।
উদাহরণ:
async function* generateSequence(start, end) {
for (let i = start; i <= end; i++) {
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate asynchronous operation
yield i;
}
}
async function consumeGenerator() {
for await (const num of generateSequence(1, 5)) {
console.log(num);
}
}
consumeGenerator(); // Output: 1, 2, 3, 4, 5 (with delays)
অ্যাসিঙ্ক স্ট্রিমে এরর হ্যান্ডলিং-এর চ্যালেঞ্জ
অ্যাসিঙ্ক্রোনাস স্ট্রিমে এরর হ্যান্ডলিং সিঙ্ক্রোনাস কোডের তুলনায় অনন্য চ্যালেঞ্জ উপস্থাপন করে। প্রচলিত try/catch ব্লকগুলি শুধুমাত্র তাৎক্ষণিক সিঙ্ক্রোনাস স্কোপের মধ্যে ঘটে যাওয়া ত্রুটিগুলি ধরতে পারে। যখন একটি অ্যাসিঙ্ক ইটারেটর বা জেনারেটরের মধ্যে অ্যাসিঙ্ক্রোনাস অপারেশনগুলির সাথে কাজ করা হয়, তখন ত্রুটিগুলি বিভিন্ন সময়ে ঘটতে পারে, যার জন্য এরর প্রোপাগেশনের একটি আরও পরিশীলিত পদ্ধতির প্রয়োজন হয়।
এমন একটি পরিস্থিতি বিবেচনা করুন যেখানে আপনি একটি রিমোট এপিআই থেকে ডেটা প্রসেস করছেন। এপিআই যেকোনো সময় একটি ত্রুটি রিটার্ন করতে পারে, যেমন একটি নেটওয়ার্ক ব্যর্থতা বা একটি সার্ভার-সাইড সমস্যা। আপনার অ্যাপ্লিকেশনকে এই ত্রুটিগুলি সুন্দরভাবে পরিচালনা করতে, সেগুলি লগ করতে এবং সম্ভবত অপারেশনটি পুনরায় চেষ্টা করতে বা একটি ফলব্যাক মান সরবরাহ করতে সক্ষম হতে হবে।
অ্যাসিঙ্ক ইটারেটর হেল্পারগুলিতে এরর প্রোপাগেশনের কৌশল
অ্যাসিঙ্ক ইটারেটর হেল্পারগুলিতে কার্যকরভাবে ত্রুটি পরিচালনা করার জন্য বেশ কয়েকটি কৌশল ব্যবহার করা যেতে পারে। আসুন কিছু সবচেয়ে সাধারণ এবং কার্যকর কৌশলগুলি অন্বেষণ করি।
১. অ্যাসিঙ্ক জেনারেটর ফাংশনের মধ্যে Try/Catch ব্লক
সবচেয়ে সহজ পদ্ধতিগুলির মধ্যে একটি হলো অ্যাসিঙ্ক জেনারেটর ফাংশনের মধ্যে অ্যাসিঙ্ক্রোনাস অপারেশনগুলিকে try/catch ব্লকে মোড়ানো। এটি আপনাকে জেনারেটরের এক্সিকিউশনের সময় ঘটে যাওয়া ত্রুটিগুলি ধরতে এবং সেই অনুযায়ী সেগুলি পরিচালনা করতে দেয়।
উদাহরণ:
async function* fetchData(urls) {
for (const url of urls) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
yield data;
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
// Optionally, yield a fallback value or re-throw the error
yield { error: error.message, url: url }; // Yield an error object
}
}
}
async function consumeData() {
for await (const item of fetchData(['https://example.com/data1', 'https://example.com/data2'])) {
if (item.error) {
console.warn(`Encountered an error for URL: ${item.url}, Error: ${item.error}`);
} else {
console.log('Received data:', item);
}
}
}
consumeData();
এই উদাহরণে, fetchData জেনারেটর ফাংশনটি ইউআরএল-এর একটি তালিকা থেকে ডেটা নিয়ে আসে। যদি ফেচ অপারেশনের সময় কোনো ত্রুটি ঘটে, তাহলে catch ব্লকটি ত্রুটিটি লগ করে এবং একটি এরর অবজেক্ট ইল্ড (yield) করে। এরপর কনজিউমার ফাংশনটি ইল্ড করা মানের মধ্যে error প্রপার্টি পরীক্ষা করে এবং সেই অনুযায়ী এটি পরিচালনা করে। এই প্যাটার্নটি নিশ্চিত করে যে ত্রুটিগুলি স্থানীয়করণ করা হয়েছে এবং জেনারেটরের মধ্যে পরিচালিত হয়েছে, যা পুরো স্ট্রিমটিকে ক্র্যাশ করা থেকে রক্ষা করে।
২. এরর হ্যান্ডলিং-এর জন্য Promise.prototype.catch ব্যবহার করা
আরেকটি সাধারণ কৌশল হলো অ্যাসিঙ্ক জেনারেটর ফাংশনের মধ্যে প্রমিসের উপর .catch() মেথড ব্যবহার করা। এটি আপনাকে একটি প্রমিস রিজলভ হওয়ার সময় ঘটে যাওয়া ত্রুটিগুলি পরিচালনা করতে দেয়।
উদাহরণ:
async function* fetchData(urls) {
for (const url of urls) {
const promise = fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error(`Error fetching data from ${url}:`, error);
return { error: error.message, url: url }; // Return an error object
});
yield await promise;
}
}
async function consumeData() {
for await (const item of fetchData(['https://example.com/data1', 'https://example.com/data2'])) {
if (item.error) {
console.warn(`Encountered an error for URL: ${item.url}, Error: ${item.error}`);
} else {
console.log('Received data:', item);
}
}
}
consumeData();
এই উদাহরণে, ফেচ অপারেশনের সময় ঘটে যাওয়া ত্রুটিগুলি পরিচালনা করতে .catch() মেথড ব্যবহার করা হয়। যদি কোনো ত্রুটি ঘটে, catch ব্লকটি ত্রুটিটি লগ করে এবং একটি এরর অবজেক্ট রিটার্ন করে। জেনারেটর ফাংশনটি তখন প্রমিসের ফলাফল ইল্ড করে, যা হয় ফেচ করা ডেটা বা এরর অবজেক্ট হবে। এই পদ্ধতিটি প্রমিস রিজলভিং-এর সময় ঘটে যাওয়া ত্রুটিগুলি পরিচালনা করার একটি পরিষ্কার এবং সংক্ষিপ্ত উপায় সরবরাহ করে।
৩. একটি কাস্টম এরর হ্যান্ডলিং হেল্পার ফাংশন প্রয়োগ করা
আরও জটিল এরর হ্যান্ডলিং পরিস্থিতির জন্য, একটি কাস্টম এরর হ্যান্ডলিং হেল্পার ফাংশন তৈরি করা উপকারী হতে পারে। এই ফাংশনটি এরর হ্যান্ডলিং লজিককে এনক্যাপসুলেট করতে পারে এবং আপনার অ্যাপ্লিকেশন জুড়ে ত্রুটিগুলি পরিচালনা করার একটি সামঞ্জস্যপূর্ণ উপায় সরবরাহ করতে পারে।
উদাহরণ:
async function safeFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
return { error: error.message, url: url }; // Return an error object
}
}
async function* fetchData(urls) {
for (const url of urls) {
yield await safeFetch(url);
}
}
async function consumeData() {
for await (const item of fetchData(['https://example.com/data1', 'https://example.com/data2'])) {
if (item.error) {
console.warn(`Encountered an error for URL: ${item.url}, Error: ${item.error}`);
} else {
console.log('Received data:', item);
}
}
}
consumeData();
এই উদাহরণে, safeFetch ফাংশনটি ফেচ অপারেশনের জন্য এরর হ্যান্ডলিং লজিককে এনক্যাপসুলেট করে। fetchData জেনারেটর ফাংশনটি তখন প্রতিটি ইউআরএল থেকে ডেটা আনতে safeFetch ফাংশন ব্যবহার করে। এই পদ্ধতিটি কোডের পুনঃব্যবহারযোগ্যতা এবং রক্ষণাবেক্ষণযোগ্যতা বাড়ায়।
৪. অ্যাসিঙ্ক ইটারেটর হেল্পার ব্যবহার: map, filter, reduce এবং এরর হ্যান্ডলিং
জাভাস্ক্রিপ্টের অ্যাসিঙ্ক ইটারেটর হেল্পার (map, filter, reduce, ইত্যাদি) অ্যাসিঙ্ক স্ট্রিমগুলিকে রূপান্তর এবং প্রসেস করার সুবিধাজনক উপায় সরবরাহ করে। এই হেল্পারগুলি ব্যবহার করার সময়, কীভাবে ত্রুটিগুলি প্রচারিত হয় এবং কীভাবে সেগুলি কার্যকরভাবে পরিচালনা করতে হয় তা বোঝা অত্যন্ত গুরুত্বপূর্ণ।
ক) map-এ এরর হ্যান্ডলিং
map হেল্পারটি অ্যাসিঙ্ক স্ট্রিমের প্রতিটি উপাদানের উপর একটি রূপান্তর ফাংশন প্রয়োগ করে। যদি রূপান্তর ফাংশনটি একটি ত্রুটি থ্রো করে, তাহলে ত্রুটিটি কনজিউমারের কাছে প্রচারিত হয়।
উদাহরণ:
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
yield i;
}
}
async function consumeData() {
try {
const asyncIterable = generateNumbers(5);
const mappedIterable = asyncIterable.map(async (num) => {
if (num === 3) {
throw new Error('Error processing number 3');
}
return num * 2;
});
for await (const item of mappedIterable) {
console.log(item);
}
} catch (error) {
console.error('An error occurred:', error);
}
}
consumeData(); // Output: 2, 4, An error occurred: Error: Error processing number 3
এই উদাহরণে, রূপান্তর ফাংশনটি ৩ নম্বর প্রসেস করার সময় একটি ত্রুটি থ্রো করে। ত্রুটিটি consumeData ফাংশনের catch ব্লক দ্বারা ধরা হয়। মনে রাখবেন যে ত্রুটিটি ইটারেশন বন্ধ করে দেয়।
খ) filter-এ এরর হ্যান্ডলিং
filter হেল্পারটি একটি প্রেডিকেট ফাংশনের উপর ভিত্তি করে অ্যাসিঙ্ক স্ট্রিমের উপাদানগুলিকে ফিল্টার করে। যদি প্রেডিকেট ফাংশনটি একটি ত্রুটি থ্রো করে, তাহলে ত্রুটিটি কনজিউমারের কাছে প্রচারিত হয়।
উদাহরণ:
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
yield i;
}
}
async function consumeData() {
try {
const asyncIterable = generateNumbers(5);
const filteredIterable = asyncIterable.filter(async (num) => {
if (num === 3) {
throw new Error('Error filtering number 3');
}
return num % 2 === 0;
});
for await (const item of filteredIterable) {
console.log(item);
}
} catch (error) {
console.error('An error occurred:', error);
}
}
consumeData(); // Output: An error occurred: Error: Error filtering number 3
এই উদাহরণে, প্রেডিকেট ফাংশনটি ৩ নম্বর প্রসেস করার সময় একটি ত্রুটি থ্রো করে। ত্রুটিটি consumeData ফাংশনের catch ব্লক দ্বারা ধরা হয়।
গ) reduce-এ এরর হ্যান্ডলিং
reduce হেল্পারটি একটি রিডিউসার ফাংশন ব্যবহার করে অ্যাসিঙ্ক স্ট্রিমকে একটি একক মানে রিডিউস করে। যদি রিডিউসার ফাংশনটি একটি ত্রুটি থ্রো করে, তাহলে ত্রুটিটি কনজিউমারের কাছে প্রচারিত হয়।
উদাহরণ:
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
yield i;
}
}
async function consumeData() {
try {
const asyncIterable = generateNumbers(5);
const sum = await asyncIterable.reduce(async (acc, num) => {
if (num === 3) {
throw new Error('Error reducing number 3');
}
return acc + num;
}, 0);
console.log('Sum:', sum);
} catch (error) {
console.error('An error occurred:', error);
}
}
consumeData(); // Output: An error occurred: Error: Error reducing number 3
এই উদাহরণে, রিডিউসার ফাংশনটি ৩ নম্বর প্রসেস করার সময় একটি ত্রুটি থ্রো করে। ত্রুটিটি consumeData ফাংশনের catch ব্লক দ্বারা ধরা হয়।
৫. process.on('unhandledRejection') (Node.js) বা window.addEventListener('unhandledrejection') (ব্রাউজার) দিয়ে গ্লোবাল এরর হ্যান্ডলিং
যদিও এটি অ্যাসিঙ্ক ইটারেটরের জন্য নির্দিষ্ট নয়, গ্লোবাল এরর হ্যান্ডলিং মেকানিজম কনফিগার করা আপনার স্ট্রিমের মধ্যে ঘটতে পারে এমন আনহ্যান্ডেলড প্রমিস রিজেকশনের জন্য একটি সুরক্ষা জাল সরবরাহ করতে পারে। এটি বিশেষত Node.js পরিবেশে গুরুত্বপূর্ণ।
Node.js উদাহরণ:
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// Optionally, perform cleanup or exit the process
});
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
if (i === 3) {
throw new Error('Simulated Error'); // This will cause an unhandled rejection if not caught locally
}
yield i;
}
}
async function main() {
const iterator = generateNumbers(5);
for await (const num of iterator) {
console.log(num);
}
}
main(); // Will trigger 'unhandledRejection' if the error inside generator isn't handled.
ব্রাউজার উদাহরণ:
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled rejection:', event.reason, event.promise);
// You can log the error or display a user-friendly message here.
});
async function fetchData(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); // Might cause unhandled rejection if `fetchData` isn't wrapped in try/catch
}
return response.json();
}
async function processData() {
const data = await fetchData('https://example.com/api/nonexistent'); // URL likely to cause an error.
console.log(data);
}
processData();
গুরুত্বপূর্ণ বিবেচ্য বিষয়:
- ডিবাগিং: গ্লোবাল হ্যান্ডলারগুলি আনহ্যান্ডেলড রিজেকশন লগিং এবং ডিবাগিং করার জন্য মূল্যবান।
- পরিষ্কার করা: অ্যাপ্লিকেশন ক্র্যাশ করার আগে আপনি এই হ্যান্ডলারগুলি ব্যবহার করে পরিষ্কার করার কাজগুলি করতে পারেন।
- ক্র্যাশ প্রতিরোধ: যদিও তারা ত্রুটিগুলি লগ করে, তবে তারা অ্যাপ্লিকেশনকে সম্ভাব্য ক্র্যাশ হওয়া থেকে আটকাতে পারে *না* যদি ত্রুটিটি মৌলিকভাবে লজিক ভেঙে দেয়। অতএব, অ্যাসিঙ্ক স্ট্রিমের মধ্যে স্থানীয় এরর হ্যান্ডলিং সর্বদা প্রাথমিক প্রতিরক্ষা।
অ্যাসিঙ্ক ইটারেটর হেল্পারে এরর হ্যান্ডলিং-এর জন্য সেরা অনুশীলন
আপনার অ্যাসিঙ্ক ইটারেটর হেল্পারগুলিতে শক্তিশালী এরর হ্যান্ডলিং নিশ্চিত করতে, নিম্নলিখিত সেরা অনুশীলনগুলি বিবেচনা করুন:
- স্থানীয় এরর হ্যান্ডলিং: ত্রুটিগুলি তাদের উৎসের যত কাছাকাছি সম্ভব পরিচালনা করুন। অ্যাসিঙ্ক্রোনাস অপারেশনের সময় ঘটে যাওয়া ত্রুটিগুলি ধরতে অ্যাসিঙ্ক জেনারেটর ফাংশনের মধ্যে
try/catchব্লক বা.catch()মেথড ব্যবহার করুন। - ফলব্যাক মান সরবরাহ করুন: যখন একটি ত্রুটি ঘটে, তখন পুরো স্ট্রিমটিকে ক্র্যাশ হওয়া থেকে রক্ষা করতে একটি ফলব্যাক মান বা একটি ডিফল্ট মান ইল্ড করার কথা বিবেচনা করুন। এটি কনজিউমারকে স্ট্রিম প্রসেসিং চালিয়ে যাওয়ার অনুমতি দেয় যদিও কিছু উপাদান অবৈধ থাকে।
- ত্রুটি লগ করুন: ডিবাগিং সহজ করার জন্য পর্যাপ্ত বিবরণ সহ ত্রুটিগুলি লগ করুন। যেমন ইউআরএল, ত্রুটির বার্তা এবং স্ট্যাক ট্রেসের মতো তথ্য অন্তর্ভুক্ত করুন।
- অপারেশন পুনরায় চেষ্টা করুন: ক্ষণস্থায়ী ত্রুটির জন্য, যেমন নেটওয়ার্ক ব্যর্থতা, একটি সংক্ষিপ্ত বিলম্বের পরে অপারেশনটি পুনরায় চেষ্টা করার কথা বিবেচনা করুন। অসীম লুপ এড়াতে সর্বোচ্চ সংখ্যক প্রচেষ্টা সহ একটি রিট্রাই মেকানিজম প্রয়োগ করুন।
- একটি কাস্টম এরর হ্যান্ডলিং হেল্পার ফাংশন ব্যবহার করুন: কোডের পুনঃব্যবহারযোগ্যতা এবং রক্ষণাবেক্ষণযোগ্যতা বাড়ানোর জন্য এরর হ্যান্ডলিং লজিককে একটি কাস্টম হেল্পার ফাংশনে এনক্যাপসুলেট করুন।
- গ্লোবাল এরর হ্যান্ডলিং বিবেচনা করুন: Node.js-এ
process.on('unhandledRejection')-এর মতো গ্লোবাল এরর হ্যান্ডলিং মেকানিজম প্রয়োগ করুন আনহ্যান্ডেলড প্রমিস রিজেকশনগুলি ধরার জন্য। তবে, প্রাথমিক প্রতিরক্ষা হিসাবে স্থানীয় এরর হ্যান্ডলিং-এর উপর নির্ভর করুন। - সঠিকভাবে শাটডাউন: সার্ভার-সাইড অ্যাপ্লিকেশনগুলিতে, নিশ্চিত করুন যে আপনার অ্যাসিঙ্ক স্ট্রিম প্রসেসিং কোড
SIGINT(Ctrl+C) এবংSIGTERM-এর মতো সিগন্যালগুলি সঠিকভাবে পরিচালনা করে ডেটা ক্ষতি রোধ করতে এবং একটি পরিষ্কার শাটডাউন নিশ্চিত করতে। এর মধ্যে রিসোর্সগুলি (ডাটাবেস সংযোগ, ফাইল হ্যান্ডেল, নেটওয়ার্ক সংযোগ) বন্ধ করা এবং কোনো পেন্ডিং অপারেশন সম্পূর্ণ করা অন্তর্ভুক্ত। - পর্যবেক্ষণ এবং সতর্কতা: আপনার অ্যাসিঙ্ক স্ট্রিম প্রসেসিং কোডে ত্রুটি সনাক্ত করতে এবং প্রতিক্রিয়া জানাতে পর্যবেক্ষণ এবং সতর্কতা সিস্টেম প্রয়োগ করুন। এটি আপনাকে সমস্যাগুলি ব্যবহারকারীদের প্রভাবিত করার আগে চিহ্নিত করতে এবং সমাধান করতে সহায়তা করবে।
বাস্তব উদাহরণ: বাস্তব-বিশ্বের পরিস্থিতিতে এরর হ্যান্ডলিং
আসুন অ্যাসিঙ্ক ইটারেটর হেল্পার জড়িত বাস্তব-বিশ্বের পরিস্থিতিতে এরর হ্যান্ডলিং-এর কিছু বাস্তব উদাহরণ পরীক্ষা করি।
উদাহরণ ১: ফলব্যাক মেকানিজম সহ একাধিক এপিআই থেকে ডেটা প্রসেসিং
কল্পনা করুন আপনাকে একাধিক এপিআই থেকে ডেটা আনতে হবে। যদি একটি এপিআই ব্যর্থ হয়, আপনি একটি ফলব্যাক এপিআই ব্যবহার করতে বা একটি ডিফল্ট মান রিটার্ন করতে চান।
async function safeFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
return null; // Indicate failure
}
}
async function* fetchDataWithFallback(apiUrls, fallbackUrl) {
for (const apiUrl of apiUrls) {
let data = await safeFetch(apiUrl);
if (data === null) {
console.log(`Attempting fallback for ${apiUrl}`);
data = await safeFetch(fallbackUrl);
if (data === null) {
console.warn(`Fallback also failed for ${apiUrl}. Returning default value.`);
yield { error: `Failed to fetch data from ${apiUrl} and fallback.` };
continue; // Skip to the next URL
}
}
yield data;
}
}
async function processData() {
const apiUrls = ['https://api.example.com/data1', 'https://api.nonexistent.com/data2', 'https://api.example.com/data3'];
const fallbackUrl = 'https://backup.example.com/default_data';
for await (const item of fetchDataWithFallback(apiUrls, fallbackUrl)) {
if (item.error) {
console.warn(`Error processing data: ${item.error}`);
} else {
console.log('Processed data:', item);
}
}
}
processData();
এই উদাহরণে, fetchDataWithFallback জেনারেটর ফাংশনটি এপিআইগুলির একটি তালিকা থেকে ডেটা আনার চেষ্টা করে। যদি একটি এপিআই ব্যর্থ হয়, এটি একটি ফলব্যাক এপিআই থেকে ডেটা আনার চেষ্টা করে। যদি ফলব্যাক এপিআইটিও ব্যর্থ হয়, এটি একটি সতর্কতা লগ করে এবং একটি এরর অবজেক্ট ইল্ড করে। এরপর কনজিউমার ফাংশনটি সেই অনুযায়ী ত্রুটিটি পরিচালনা করে।
উদাহরণ ২: এরর হ্যান্ডলিং সহ রেট লিমিটিং
এপিআইগুলির সাথে ইন্টারঅ্যাক্ট করার সময়, বিশেষ করে থার্ড-পার্টি এপিআইগুলির সাথে, আপনাকে প্রায়শই এপিআই-এর ব্যবহারের সীমা অতিক্রম করা এড়াতে রেট লিমিটিং প্রয়োগ করতে হয়। রেট লিমিট ত্রুটিগুলি পরিচালনা করার জন্য সঠিক এরর হ্যান্ডলিং অপরিহার্য।
const rateLimit = 5; // Number of requests per second
let requestCount = 0;
let lastRequestTime = 0;
async function throttledFetch(url) {
const now = Date.now();
if (requestCount >= rateLimit && now - lastRequestTime < 1000) {
const delay = 1000 - (now - lastRequestTime);
console.log(`Rate limit exceeded. Waiting ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
try {
const response = await fetch(url);
if (response.status === 429) { // Rate limit exceeded
console.warn('Rate limit exceeded. Retrying after a delay...');
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait longer
return throttledFetch(url); // Retry
}
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
requestCount++;
lastRequestTime = Date.now();
return data;
} catch (error) {
console.error(`Error fetching ${url}:`, error);
throw error; // Re-throw the error after logging
}
}
async function* fetchUrls(urls) {
for (const url of urls) {
try {
yield await throttledFetch(url);
} catch (err) {
console.error(`Failed to fetch URL ${url} after retries. Skipping.`);
yield { error: `Failed to fetch ${url}` }; // Signal error to consumer
}
}
}
async function consumeData() {
const urls = ['https://api.example.com/resource1', 'https://api.example.com/resource2', 'https://api.example.com/resource3'];
for await (const item of fetchUrls(urls)) {
if (item.error) {
console.warn(`Error: ${item.error}`);
} else {
console.log('Data:', item);
}
}
}
consumeData();
এই উদাহরণে, throttledFetch ফাংশনটি এক সেকেন্ডের মধ্যে করা অনুরোধের সংখ্যা ট্র্যাক করে রেট লিমিটিং প্রয়োগ করে। যদি রেট লিমিট অতিক্রম করা হয়, এটি পরবর্তী অনুরোধ করার আগে একটি সংক্ষিপ্ত বিলম্বের জন্য অপেক্ষা করে। যদি একটি 429 (Too Many Requests) ত্রুটি পাওয়া যায়, এটি আরও বেশি সময় অপেক্ষা করে এবং অনুরোধটি পুনরায় চেষ্টা করে। ত্রুটিগুলিও লগ করা হয় এবং কলার দ্বারা পরিচালিত হওয়ার জন্য পুনরায় থ্রো করা হয়।
উপসংহার
এরর হ্যান্ডলিং অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং-এর একটি গুরুত্বপূর্ণ দিক, বিশেষ করে যখন অ্যাসিঙ্ক ইটারেটর এবং অ্যাসিঙ্ক জেনারেটর ফাংশনগুলির সাথে কাজ করা হয়। এরর প্রোপাগেশনের কৌশলগুলি বোঝা এবং সেরা অনুশীলনগুলি প্রয়োগ করার মাধ্যমে, আপনি শক্তিশালী এবং নির্ভরযোগ্য স্ট্রিমিং অ্যাপ্লিকেশন তৈরি করতে পারেন যা সুন্দরভাবে ত্রুটিগুলি পরিচালনা করে এবং অপ্রত্যাশিত ক্র্যাশ প্রতিরোধ করে। স্থানীয় এরর হ্যান্ডলিং-কে অগ্রাধিকার দিতে, ফলব্যাক মান সরবরাহ করতে, কার্যকরভাবে ত্রুটি লগ করতে এবং অতিরিক্ত স্থিতিস্থাপকতার জন্য গ্লোবাল এরর হ্যান্ডলিং মেকানিজম বিবেচনা করতে মনে রাখবেন। সর্বদা ব্যর্থতার জন্য ডিজাইন করুন এবং আপনার অ্যাপ্লিকেশনগুলিকে ত্রুটি থেকে সুন্দরভাবে পুনরুদ্ধার করার জন্য তৈরি করুন।