বাংলা

জাভাস্ক্রিপ্ট অ্যাসিঙ্ক ইটারেটর হেল্পার ব্যবহার করে স্ট্রিম প্রসেসিং-এ বিপ্লব আনুন। map, filter, take, drop এবং আরও অনেক কিছুর সাহায্যে অ্যাসিঙ্ক্রোনাস ডেটা স্ট্রিম দক্ষতার সাথে পরিচালনা করতে শিখুন।

জাভাস্ক্রিপ্ট অ্যাসিঙ্ক ইটারেটর হেল্পার: আধুনিক অ্যাপ্লিকেশনের জন্য শক্তিশালী স্ট্রিম প্রসেসিং

আধুনিক জাভাস্ক্রিপ্ট ডেভেলপমেন্টে, অ্যাসিঙ্ক্রোনাস ডেটা স্ট্রিম নিয়ে কাজ করা একটি সাধারণ প্রয়োজনীয়তা। আপনি এপিআই থেকে ডেটা আনুন, বড় ফাইল প্রসেস করুন বা রিয়েল-টাইম ইভেন্ট পরিচালনা করুন, অ্যাসিঙ্ক্রোনাস ডেটা দক্ষতার সাথে পরিচালনা করা অত্যন্ত গুরুত্বপূর্ণ। জাভাস্ক্রিপ্টের অ্যাসিঙ্ক ইটারেটর হেল্পার এই স্ট্রিমগুলো প্রসেস করার জন্য একটি শক্তিশালী এবং সুন্দর উপায় সরবরাহ করে, যা ডেটা ম্যানিপুলেশনের জন্য একটি ফাংশনাল এবং কম্পোজেবল পদ্ধতি প্রদান করে।

অ্যাসিঙ্ক ইটারেটর এবং অ্যাসিঙ্ক ইটারেবল কী?

অ্যাসিঙ্ক ইটারেটর হেল্পার সম্পর্কে জানার আগে, আসুন এর মূল ধারণাগুলো বুঝে নিই: অ্যাসিঙ্ক ইটারেটর এবং অ্যাসিঙ্ক ইটারেবল।

একটি অ্যাসিঙ্ক ইটারেবল হলো একটি অবজেক্ট যা তার মানগুলোর উপর অ্যাসিঙ্ক্রোনাসভাবে ইটারেট করার একটি উপায় সংজ্ঞায়িত করে। এটি @@asyncIterator মেথড প্রয়োগ করে এটি করে, যা একটি অ্যাসিঙ্ক ইটারেটর রিটার্ন করে।

একটি অ্যাসিঙ্ক ইটারেটর হলো একটি অবজেক্ট যা একটি next() মেথড সরবরাহ করে। এই মেথডটি একটি প্রমিজ (promise) রিটার্ন করে যা দুটি প্রপার্টিসহ একটি অবজেক্টে রিজলভ হয়:

এখানে একটি সহজ উদাহরণ দেওয়া হলো:


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 500)); // একটি অ্যাসিঙ্ক্রোনাস অপারেশন সিমুলেট করা হচ্ছে
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  for await (const value of asyncIterable) {
    console.log(value); // আউটপুট: 1, 2, 3, 4, 5 (প্রত্যেকটির মধ্যে ৫০০ms বিলম্ব সহ)
  }
})();

এই উদাহরণে, generateSequence একটি অ্যাসিঙ্ক জেনারেটর ফাংশন যা অ্যাসিঙ্ক্রোনাসভাবে সংখ্যার একটি ক্রম তৈরি করে। for await...of লুপটি অ্যাসিঙ্ক ইটারেবল থেকে মানগুলো গ্রহণ করতে ব্যবহৃত হয়।

অ্যাসিঙ্ক ইটারেটর হেল্পার পরিচিতি

অ্যাসিঙ্ক ইটারেটর হেল্পার অ্যাসিঙ্ক ইটারেটরের কার্যকারিতা প্রসারিত করে, যা অ্যাসিঙ্ক্রোনাস ডেটা স্ট্রিম রূপান্তর, ফিল্টার এবং ম্যানিপুলেট করার জন্য একগুচ্ছ মেথড সরবরাহ করে। তারা একটি ফাংশনাল এবং কম্পোজেবল প্রোগ্রামিং শৈলী সক্ষম করে, যা জটিল ডেটা প্রসেসিং পাইপলাইন তৈরি করা সহজ করে তোলে।

মূল অ্যাসিঙ্ক ইটারেটর হেল্পারগুলোর মধ্যে রয়েছে:

আসুন প্রতিটি হেল্পার উদাহরণসহ অন্বেষণ করি।

map()

map() হেল্পার প্রদত্ত ফাংশন ব্যবহার করে অ্যাসিঙ্ক ইটারেবলের প্রতিটি উপাদানকে রূপান্তর করে। এটি রূপান্তরিত মানসহ একটি নতুন অ্যাসিঙ্ক ইটারেবল রিটার্ন করে।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

const doubledIterable = asyncIterable.map(x => x * 2);

(async () => {
  for await (const value of doubledIterable) {
    console.log(value); // আউটপুট: 2, 4, 6, 8, 10 (100ms বিলম্ব সহ)
  }
})();

এই উদাহরণে, map(x => x * 2) সিকোয়েন্সের প্রতিটি সংখ্যাকে দ্বিগুণ করে।

filter()

filter() হেল্পার প্রদত্ত শর্ত (প্রেডিকেট ফাংশন) এর উপর ভিত্তি করে অ্যাসিঙ্ক ইটারেবল থেকে উপাদান নির্বাচন করে। এটি শুধুমাত্র শর্ত পূরণকারী উপাদানগুলোসহ একটি নতুন অ্যাসিঙ্ক ইটারেবল রিটার্ন করে।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(10);

const evenNumbersIterable = asyncIterable.filter(x => x % 2 === 0);

(async () => {
  for await (const value of evenNumbersIterable) {
    console.log(value); // আউটপুট: 2, 4, 6, 8, 10 (100ms বিলম্ব সহ)
  }
})();

এই উদাহরণে, filter(x => x % 2 === 0) সিকোয়েন্স থেকে শুধুমাত্র জোড় সংখ্যাগুলো নির্বাচন করে।

take()

take() হেল্পার অ্যাসিঙ্ক ইটারেবল থেকে প্রথম N সংখ্যক উপাদান রিটার্ন করে। এটি শুধুমাত্র নির্দিষ্ট সংখ্যক উপাদানসহ একটি নতুন অ্যাসিঙ্ক ইটারেবল রিটার্ন করে।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

const firstThreeIterable = asyncIterable.take(3);

(async () => {
  for await (const value of firstThreeIterable) {
    console.log(value); // আউটপুট: 1, 2, 3 (100ms বিলম্ব সহ)
  }
})();

এই উদাহরণে, take(3) সিকোয়েন্স থেকে প্রথম তিনটি সংখ্যা নির্বাচন করে।

drop()

drop() হেল্পার অ্যাসিঙ্ক ইটারেবল থেকে প্রথম N সংখ্যক উপাদান বাদ দিয়ে বাকিগুলো রিটার্ন করে। এটি অবশিষ্ট উপাদানগুলোসহ একটি নতুন অ্যাসিঙ্ক ইটারেবল রিটার্ন করে।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

const afterFirstTwoIterable = asyncIterable.drop(2);

(async () => {
  for await (const value of afterFirstTwoIterable) {
    console.log(value); // আউটপুট: 3, 4, 5 (100ms বিলম্ব সহ)
  }
})();

এই উদাহরণে, drop(2) সিকোয়েন্স থেকে প্রথম দুটি সংখ্যা বাদ দেয়।

toArray()

toArray() হেল্পার সম্পূর্ণ অ্যাসিঙ্ক ইটারেবলটি ব্যবহার করে এবং সমস্ত উপাদানকে একটি অ্যারেতে সংগ্রহ করে। এটি একটি প্রমিজ রিটার্ন করে যা সমস্ত উপাদানসহ একটি অ্যারেতে রিজলভ হয়।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const numbersArray = await asyncIterable.toArray();
  console.log(numbersArray); // আউটপুট: [1, 2, 3, 4, 5]
})();

এই উদাহরণে, toArray() সিকোয়েন্স থেকে সমস্ত সংখ্যা একটি অ্যারেতে সংগ্রহ করে।

forEach()

forEach() হেল্পার অ্যাসিঙ্ক ইটারেবলের প্রতিটি উপাদানের জন্য একবার প্রদত্ত ফাংশনটি কার্যকর করে। এটি একটি নতুন অ্যাসিঙ্ক ইটারেবল রিটার্ন করে *না*, এটি ফাংশনটিকে সাইড-এফেক্ট হিসেবে কার্যকর করে। এটি লগিং বা UI আপডেট করার মতো ক্রিয়াকলাপের জন্য দরকারী হতে পারে।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(3);

(async () => {
  await asyncIterable.forEach(value => {
    console.log("Value:", value);
  });
  console.log("forEach completed");
})();
// আউটপুট: Value: 1, Value: 2, Value: 3, forEach completed

some()

some() হেল্পার পরীক্ষা করে যে অ্যাসিঙ্ক ইটারেবলের অন্তত একটি উপাদান প্রদত্ত ফাংশন দ্বারা বাস্তবায়িত পরীক্ষাটি পাস করে কিনা। এটি একটি প্রমিজ রিটার্ন করে যা একটি বুলিয়ান মানে (true যদি অন্তত একটি উপাদান শর্ত পূরণ করে, অন্যথায় false) রিজলভ হয়।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const hasEvenNumber = await asyncIterable.some(x => x % 2 === 0);
  console.log("Has even number:", hasEvenNumber); // আউটপুট: Has even number: true
})();

every()

every() হেল্পার পরীক্ষা করে যে অ্যাসিঙ্ক ইটারেবলের সমস্ত উপাদান প্রদত্ত ফাংশন দ্বারা বাস্তবায়িত পরীক্ষাটি পাস করে কিনা। এটি একটি প্রমিজ রিটার্ন করে যা একটি বুলিয়ান মানে (true যদি সমস্ত উপাদান শর্ত পূরণ করে, অন্যথায় false) রিজলভ হয়।


async function* generateSequence(end) {
  for (let i = 2; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(4);

(async () => {
  const areAllEven = await asyncIterable.every(x => x % 2 === 0);
  console.log("Are all even:", areAllEven); // আউটপুট: Are all even: true
})();

find()

find() হেল্পার অ্যাসিঙ্ক ইটারেবলের প্রথম উপাদানটি রিটার্ন করে যা প্রদত্ত টেস্টিং ফাংশনটি পূরণ করে। যদি কোনো মান টেস্টিং ফাংশনটি পূরণ না করে, তবে undefined রিটার্ন করা হয়। এটি একটি প্রমিজ রিটার্ন করে যা পাওয়া উপাদান বা undefined-এ রিজলভ হয়।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const firstEven = await asyncIterable.find(x => x % 2 === 0);
  console.log("First even number:", firstEven); // আউটপুট: First even number: 2
})();

reduce()

reduce() হেল্পার অ্যাসিঙ্ক ইটারেবলের প্রতিটি উপাদানের উপর ব্যবহারকারী-সরবরাহকৃত "রিডিউসার" কলব্যাক ফাংশনটি ক্রমানুসারে কার্যকর করে, পূর্ববর্তী উপাদানের গণনার রিটার্ন মানটি পাস করে। সমস্ত উপাদানের উপর রিডিউসার চালানোর চূড়ান্ত ফলাফল একটি একক মান। এটি একটি প্রমিজ রিটার্ন করে যা চূড়ান্ত সঞ্চিত মানে রিজলভ হয়।


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const sum = await asyncIterable.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
  console.log("Sum:", sum); // আউটপুট: Sum: 15
})();

বাস্তব উদাহরণ এবং ব্যবহার

অ্যাসিঙ্ক ইটারেটর হেল্পার বিভিন্ন পরিস্থিতিতে মূল্যবান। আসুন কিছু বাস্তব উদাহরণ অন্বেষণ করি:

১. একটি স্ট্রিমিং API থেকে ডেটা প্রসেসিং

ভাবুন আপনি একটি রিয়েল-টাইম ডেটা ভিজ্যুয়ালাইজেশন ড্যাশবোর্ড তৈরি করছেন যা একটি স্ট্রিমিং API থেকে ডেটা গ্রহণ করে। API ক্রমাগত আপডেট পাঠায়, এবং আপনাকে সর্বশেষ তথ্য প্রদর্শনের জন্য এই আপডেটগুলো প্রসেস করতে হবে।


async function* fetchDataFromAPI(url) {
  let response = await fetch(url);

  if (!response.body) {
    throw new Error("ReadableStream not supported in this environment");
  }

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        break;
      }
      const chunk = decoder.decode(value);
      // ধরা যাক API নিউলাইন দ্বারা পৃথক করা JSON অবজেক্ট পাঠায়
      const lines = chunk.split('\n');
      for (const line of lines) {
        if (line.trim() !== '') {
          yield JSON.parse(line);
        }
      }
    }
  } finally {
    reader.releaseLock();
  }
}

const apiURL = 'https://example.com/streaming-api'; // আপনার API URL দিয়ে প্রতিস্থাপন করুন
const dataStream = fetchDataFromAPI(apiURL);

// ডেটা স্ট্রিম প্রসেস করুন
(async () => {
  for await (const data of dataStream.filter(item => item.type === 'metric').map(item => ({ timestamp: item.timestamp, value: item.value }))) {
    console.log('Processed Data:', data);
    // প্রসেস করা ডেটা দিয়ে ড্যাশবোর্ড আপডেট করুন
  }
})();

এই উদাহরণে, fetchDataFromAPI একটি স্ট্রিমিং API থেকে ডেটা আনে, JSON অবজেক্টগুলো পার্স করে এবং সেগুলোকে একটি অ্যাসিঙ্ক ইটারেবল হিসাবে yield করে। filter হেল্পার শুধুমাত্র মেট্রিকগুলো নির্বাচন করে এবং map হেল্পার ড্যাশবোর্ড আপডেট করার আগে ডেটাটিকে কাঙ্ক্ষিত ফর্ম্যাটে রূপান্তরিত করে।

২. বড় ফাইল পড়া এবং প্রসেসিং

ধরুন আপনাকে গ্রাহকের ডেটা সম্বলিত একটি বড় CSV ফাইল প্রসেস করতে হবে। পুরো ফাইলটি মেমরিতে লোড করার পরিবর্তে, আপনি অ্যাসিঙ্ক ইটারেটর হেল্পার ব্যবহার করে এটি খণ্ডে খণ্ডে প্রসেস করতে পারেন।


async function* readLinesFromFile(filePath) {
  const file = await fsPromises.open(filePath, 'r');

  try {
    let buffer = Buffer.alloc(1024);
    let fileOffset = 0;
    let remainder = '';

    while (true) {
      const { bytesRead } = await file.read(buffer, 0, buffer.length, fileOffset);
      if (bytesRead === 0) {
        if (remainder) {
          yield remainder;
        }
        break;
      }

      fileOffset += bytesRead;
      const chunk = buffer.toString('utf8', 0, bytesRead);
      const lines = chunk.split('\n');

      lines[0] = remainder + lines[0];
      remainder = lines.pop() || '';

      for (const line of lines) {
        yield line;
      }
    }
  } finally {
    await file.close();
  }
}

const filePath = './customer_data.csv'; // আপনার ফাইলের পাথ দিয়ে প্রতিস্থাপন করুন
const lines = readLinesFromFile(filePath);

// লাইনগুলো প্রসেস করুন
(async () => {
  for await (const customerData of lines.drop(1).map(line => line.split(',')).filter(data => data[2] === 'USA')) {
    console.log('Customer from USA:', customerData);
    // USA থেকে আসা গ্রাহকের ডেটা প্রসেস করুন
  }
})();

এই উদাহরণে, readLinesFromFile ফাইলটি লাইন বাই লাইন পড়ে এবং প্রতিটি লাইন একটি অ্যাসিঙ্ক ইটারেবল হিসাবে yield করে। drop(1) হেল্পার হেডার সারিটি এড়িয়ে যায়, map হেল্পার লাইনটিকে কলামে বিভক্ত করে এবং filter হেল্পার শুধুমাত্র USA থেকে আসা গ্রাহকদের নির্বাচন করে।

৩. রিয়েল-টাইম ইভেন্ট হ্যান্ডলিং

অ্যাসিঙ্ক ইটারেটর হেল্পার ওয়েবসকেটের মতো উৎস থেকে রিয়েল-টাইম ইভেন্ট পরিচালনা করতেও ব্যবহার করা যেতে পারে। আপনি একটি অ্যাসিঙ্ক ইটারেবল তৈরি করতে পারেন যা ইভেন্টগুলো আসার সাথে সাথে এমিট করে এবং তারপরে এই ইভেন্টগুলো প্রসেস করতে হেল্পারগুলো ব্যবহার করতে পারেন।


async function* createWebSocketStream(url) {
  const ws = new WebSocket(url);

  yield new Promise((resolve, reject) => {
      ws.onopen = () => {
          resolve();
      };
      ws.onerror = (error) => {
          reject(error);
      };
  });

  try {
    while (ws.readyState === WebSocket.OPEN) {
      yield new Promise((resolve, reject) => {
        ws.onmessage = (event) => {
          resolve(JSON.parse(event.data));
        };
        ws.onerror = (error) => {
          reject(error);
        };
        ws.onclose = () => {
           resolve(null); // সংযোগ বন্ধ হলে null দিয়ে রিজলভ করুন
        }
      });

    }
  } finally {
    ws.close();
  }
}

const websocketURL = 'wss://example.com/events'; // আপনার WebSocket URL দিয়ে প্রতিস্থাপন করুন
const eventStream = createWebSocketStream(websocketURL);

// ইভেন্ট স্ট্রিম প্রসেস করুন
(async () => {
  for await (const event of eventStream.filter(event => event.type === 'user_login').map(event => ({ userId: event.userId, timestamp: event.timestamp }))) {
    console.log('User Login Event:', event);
    // ব্যবহারকারীর লগইন ইভেন্ট প্রসেস করুন
  }
})();

এই উদাহরণে, createWebSocketStream একটি অ্যাসিঙ্ক ইটারেবল তৈরি করে যা একটি ওয়েবসকেট থেকে প্রাপ্ত ইভেন্টগুলো এমিট করে। filter হেল্পার শুধুমাত্র ব্যবহারকারীর লগইন ইভেন্ট নির্বাচন করে এবং map হেল্পার ডেটাটিকে কাঙ্ক্ষিত ফর্ম্যাটে রূপান্তরিত করে।

অ্যাসিঙ্ক ইটারেটর হেল্পার ব্যবহারের সুবিধা

ব্রাউজার এবং রানটাইম সাপোর্ট

অ্যাসিঙ্ক ইটারেটর হেল্পার জাভাস্ক্রিপ্টে এখনও একটি তুলনামূলকভাবে নতুন বৈশিষ্ট্য। ২০২৪ সালের শেষের দিকে, এটি TC39 স্ট্যান্ডার্ডাইজেশন প্রক্রিয়ার স্টেজ ৩-এ রয়েছে, যার অর্থ এটি অদূর ভবিষ্যতে স্ট্যান্ডার্ডাইজড হওয়ার সম্ভাবনা রয়েছে। তবে, এটি এখনও সমস্ত ব্রাউজার এবং Node.js সংস্করণে স্থানীয়ভাবে সমর্থিত নয়।

ব্রাউজার সাপোর্ট: ক্রোম, ফায়ারফক্স, সাফারি এবং এজের মতো আধুনিক ব্রাউজারগুলো ধীরে ধীরে অ্যাসিঙ্ক ইটারেটর হেল্পারগুলোর জন্য সাপোর্ট যোগ করছে। কোন ব্রাউজারগুলো এই বৈশিষ্ট্যটি সমর্থন করে তা দেখতে আপনি Can I use... এর মতো ওয়েবসাইটগুলোতে সর্বশেষ ব্রাউজার সামঞ্জস্যতার তথ্য পরীক্ষা করতে পারেন।

Node.js সাপোর্ট: Node.js-এর সাম্প্রতিক সংস্করণগুলো (v18 এবং তার উপরে) অ্যাসিঙ্ক ইটারেটর হেল্পারগুলোর জন্য পরীক্ষামূলক সাপোর্ট সরবরাহ করে। এগুলো ব্যবহার করার জন্য, আপনাকে --experimental-async-iterator ফ্ল্যাগ দিয়ে Node.js চালাতে হতে পারে।

পলিফিলস (Polyfills): যদি আপনাকে এমন পরিবেশে অ্যাসিঙ্ক ইটারেটর হেল্পার ব্যবহার করতে হয় যেখানে এটি স্থানীয়ভাবে সমর্থিত নয়, আপনি একটি পলিফিল ব্যবহার করতে পারেন। একটি পলিফিল হলো কোডের একটি অংশ যা অনুপস্থিত কার্যকারিতা সরবরাহ করে। অ্যাসিঙ্ক ইটারেটর হেল্পারগুলোর জন্য বেশ কয়েকটি পলিফিল লাইব্রেরি উপলব্ধ; একটি জনপ্রিয় বিকল্প হলো core-js লাইব্রেরি।

কাস্টম অ্যাসিঙ্ক ইটারেটর বাস্তবায়ন

যদিও অ্যাসিঙ্ক ইটারেটর হেল্পার বিদ্যমান অ্যাসিঙ্ক ইটারেবল প্রসেস করার একটি সুবিধাজনক উপায় সরবরাহ করে, কখনও কখনও আপনাকে আপনার নিজস্ব কাস্টম অ্যাসিঙ্ক ইটারেটর তৈরি করতে হতে পারে। এটি আপনাকে বিভিন্ন উৎস থেকে ডেটা, যেমন ডেটাবেস, এপিআই বা ফাইল সিস্টেম, একটি স্ট্রিমিং পদ্ধতিতে পরিচালনা করতে দেয়।

একটি কাস্টম অ্যাসিঙ্ক ইটারেটর তৈরি করতে, আপনাকে একটি অবজেক্টে @@asyncIterator মেথডটি বাস্তবায়ন করতে হবে। এই মেথডটিকে একটি next() মেথডসহ একটি অবজেক্ট রিটার্ন করা উচিত। next() মেথডটিকে একটি প্রমিজ রিটার্ন করা উচিত যা value এবং done প্রপার্টিসহ একটি অবজেক্টে রিজলভ হয়।

এখানে একটি পেজিনেটেড এপিআই থেকে ডেটা আনার জন্য একটি কাস্টম অ্যাসিঙ্ক ইটারেটরের উদাহরণ দেওয়া হলো:


async function* fetchPaginatedData(baseURL) {
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const url = `${baseURL}?page=${page}`;
    const response = await fetch(url);
    const data = await response.json();

    if (data.results.length === 0) {
      hasMore = false;
      break;
    }

    for (const item of data.results) {
      yield item;
    }

    page++;
  }
}

const apiBaseURL = 'https://api.example.com/data'; // আপনার API URL দিয়ে প্রতিস্থাপন করুন
const paginatedData = fetchPaginatedData(apiBaseURL);

// পেজিনেটেড ডেটা প্রসেস করুন
(async () => {
  for await (const item of paginatedData) {
    console.log('Item:', item);
    // আইটেমটি প্রসেস করুন
  }
})();

এই উদাহরণে, fetchPaginatedData একটি পেজিনেটেড এপিআই থেকে ডেটা আনে এবং প্রতিটি আইটেম পুনরুদ্ধার হওয়ার সাথে সাথে yield করে। অ্যাসিঙ্ক ইটারেটর পেজিনেশন লজিক পরিচালনা করে, যা ডেটাটিকে একটি স্ট্রিমিং পদ্ধতিতে ব্যবহার করা সহজ করে তোলে।

সম্ভাব্য চ্যালেঞ্জ এবং বিবেচনা

যদিও অ্যাসিঙ্ক ইটারেটর হেল্পার অনেক সুবিধা প্রদান করে, কিছু সম্ভাব্য চ্যালেঞ্জ এবং বিবেচনার বিষয়ে সচেতন থাকা গুরুত্বপূর্ণ:

অ্যাসিঙ্ক ইটারেটর হেল্পার ব্যবহারের সেরা অনুশীলন

অ্যাসিঙ্ক ইটারেটর হেল্পার থেকে সর্বাধিক সুবিধা পেতে, নিম্নলিখিত সেরা অনুশীলনগুলো বিবেচনা করুন:

উন্নত কৌশল

কাস্টম হেল্পার কম্পোজ করা

আপনি বিদ্যমান হেল্পারগুলো কম্পোজ করে বা স্ক্র্যাচ থেকে নতুন তৈরি করে আপনার নিজস্ব কাস্টম অ্যাসিঙ্ক ইটারেটর হেল্পার তৈরি করতে পারেন। এটি আপনাকে আপনার নির্দিষ্ট প্রয়োজনের জন্য কার্যকারিতা তৈরি করতে এবং পুনঃব্যবহারযোগ্য উপাদান তৈরি করতে দেয়।


async function* takeWhile(asyncIterable, predicate) {
  for await (const value of asyncIterable) {
    if (!predicate(value)) {
      break;
    }
    yield value;
  }
}

// উদাহরণ ব্যবহার:
async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(10);
const firstFive = takeWhile(asyncIterable, x => x <= 5);

(async () => {
  for await (const value of firstFive) {
    console.log(value);
  }
})();

একাধিক অ্যাসিঙ্ক ইটারেবল একত্রিত করা

আপনি zip বা merge এর মতো কৌশল ব্যবহার করে একাধিক অ্যাসিঙ্ক ইটারেবলকে একটি একক অ্যাসিঙ্ক ইটারেবলে একত্রিত করতে পারেন। এটি আপনাকে একই সাথে একাধিক উৎস থেকে ডেটা প্রসেস করতে দেয়।


async function* zip(asyncIterable1, asyncIterable2) {
    const iterator1 = asyncIterable1[Symbol.asyncIterator]();
    const iterator2 = asyncIterable2[Symbol.asyncIterator]();

    while (true) {
        const result1 = await iterator1.next();
        const result2 = await iterator2.next();

        if (result1.done || result2.done) {
            break;
        }

        yield [result1.value, result2.value];
    }
}

// উদাহরণ ব্যবহার:
async function* generateSequence1(end) {
    for (let i = 1; i <= end; i++) {
        yield i;
    }
}

async function* generateSequence2(end) {
    for (let i = 10; i <= end + 9; i++) {
        yield i;
    }
}

const iterable1 = generateSequence1(5);
const iterable2 = generateSequence2(5);

(async () => {
    for await (const [value1, value2] of zip(iterable1, iterable2)) {
        console.log(value1, value2);
    }
})();

উপসংহার

জাভাস্ক্রিপ্ট অ্যাসিঙ্ক ইটারেটর হেল্পার অ্যাসিঙ্ক্রোনাস ডেটা স্ট্রিম প্রসেস করার জন্য একটি শক্তিশালী এবং সুন্দর উপায় সরবরাহ করে। তারা ডেটা ম্যানিপুলেশনের জন্য একটি ফাংশনাল এবং কম্পোজেবল পদ্ধতি প্রদান করে, যা জটিল ডেটা প্রসেসিং পাইপলাইন তৈরি করা সহজ করে তোলে। অ্যাসিঙ্ক ইটারেটর এবং অ্যাসিঙ্ক ইটারেবলের মূল ধারণাগুলো বুঝে এবং বিভিন্ন হেল্পার মেথডগুলো আয়ত্ত করে, আপনি আপনার অ্যাসিঙ্ক্রোনাস জাভাস্ক্রিপ্ট কোডের দক্ষতা এবং রক্ষণাবেক্ষণযোগ্যতা উল্লেখযোগ্যভাবে উন্নত করতে পারেন। যেহেতু ব্রাউজার এবং রানটাইম সাপোর্ট বাড়তে থাকবে, অ্যাসিঙ্ক ইটারেটর হেল্পার আধুনিক জাভাস্ক্রিপ্ট ডেভেলপারদের জন্য একটি অপরিহার্য সরঞ্জাম হতে চলেছে।

জাভাস্ক্রিপ্ট অ্যাসিঙ্ক ইটারেটর হেল্পার: আধুনিক অ্যাপ্লিকেশনের জন্য শক্তিশালী স্ট্রিম প্রসেসিং | MLOG