5.2 কিভাবে অ্যাসিঙ্ক্রোনাস জাভাস্ক্ৰিপ্ট হ্যান্ডেল করবেন

 

জাভাস্ক্রিপ্টে অ্যাসিঙ্ক্রোনাস কোড লেখার তিনটি উপায় আছে, কলব্যাক, প্রমিজ এবং অ্যাসিঙ্ক/এওয়েট। চলুন একটি একটি করে আলোচনা করা যাক।

কলব্যাক:

কলব্যাক ফাংশনের মানে এক কথায় এটা এমন একটা ফাংশন যেটা আরেকটা ফাংশন এক্সিকিউট হওয়ার পর এক্সিকিউট হয়। আর এজন্যেই এটার নাম কলব্যাক ফাংশন। আমরা জাভাস্ক্রিপ্টে Higher Order Function এর কথা জানি। যেখানে একটা ফাংশন আরেকটা ফাংশন return করতে পারে আবার একই সাথে একটা ফাংশন আর্গুমেন্ট হিসেবে আরেকটা ফাংশনকেও নিতে পারে। যখনি এরকম একটা ফাংশন আরেকটা ফাংশনকে আর্গুমেন্ট হিসেবে নেয়, তখনি আমরা সেই আর্গুমেন্টে যাওয়া ফাংশনটাকে কলব্যাক ফাংশন বলি।

মাঝেমধ্যে আমরা আমাদের কোডের সিকুয়েন্স নিয়ন্ত্রণ করতে চাই, তখন আমরা খুব সহজেই কলব্যাক ফাংশন ব্যবহার করতে পারি। নিচের কোডটি খেয়াল করি, আমরা কলব্যাক ফাংশন ব্যবহার করে খুব সহজেই আগে যোগ করে তারপর আউটপুট দেখাচ্ছি।

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myCalculator(num1, num2) {
  let sum = num1 + num2;
  return sum;
}

let result = myCalculator(5, 5);
myDisplayer(result);

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

const function1 = () => {
   setTimeout(function() {
      console.log('1st Function');
   }, 3000)
}
const function2 = () => {
   console.log('2nd Function');
}
function1();
function2();

উপরে যদিও ১ম ফাংশন প্রথমে কল করা হয়েছে, কিন্তু অ্যাসিনক্রোনাস আচরণের জন্য আগে ২য় ফাংশন কল হবে। 

কলব্যাকের ফাংশনের সংজ্ঞা থেকে আমরা জেনেছিলাম এটা আরেকটা ফাংশন এক্সিকিউট হলে পরেই এক্সিকিউট হয়। আর তাই আমরা এখানে এই টেকনিকটা ইউজ করে এরকম পৃথক পৃথকভাবে দুইটা ফাংশন লিখেও কলব্যাকের মাধ্যমে ঠিক যেসময় ফাংশনটাকে কল করা দরকার সেসময়েই করতে পারবো। 

const function1 = (callback) => {
   setTimeout(function() {
      console.log('1st Function');
      callback();
   }, 3000)
}
const function2 = () => {
   console.log('2nd Function');
}
function1(function2);

আমরা এখানে আমাদের মেইন ফাংশন কলের ভিতরে আর্গুমেন্ট হিসেবে আমাদের ফাংশনটাকে পাস করে দিলাম। আর সেটা পরে ঠিক যেখানে দরকার সেখানেই কল করলাম। এটা আমাদের মনের মতো ফলাফল দিবে। মানে একটার পরে আরেকটা। এটা ঠিকই ৩ সেকেন্ড ওয়েট করবে তারপর ফলাফল দিবে। কিন্তু সিরিয়াল মেইন্টেইন করে।

প্রমিজ:

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

let myPromise = new Promise(function(myResolve, myReject) {
// "Producing Code" (May take some time)

  myResolve(); // when successful
  myReject();  // when error
});

// "Consuming Code" (Must wait for a fulfilled Promise)

myPromise.then(
  function(value) { /* code if successful */ },
  function(error) { /* code if some error */ }
);

যখনি Producing কোড ফলাফল পেয়ে যায়, এইটা তখন নিচের দুইটা কলব্যাক থেকে একটাকে কল করে।

ফলাফল কল
Success myResolve(result value)
Error myReject(error object)

এখন প্রমিস অবজেক্ট আবার ৩ ধরণের হতে পারে, যেমনঃ 

  • Pending
  • Fulfilled
  • Rejected

Pending অবস্থায় ফলাফল undefined, Fulfilled অবস্থায় ফলাফল একটি ভ্যালু, এবং Rejected অবস্থায় ফলাফল একটি error অবজেক্ট।

নিচের মতো করে প্রমিস ব্যবহার করতে হয়ঃ 

myPromise.then(
  function(value) { /* code if successful */ },
  function(error) { /* code if some error */ }
);

 

async এবং await:

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

জাভস্ক্রিপ্ট-এ মূলত প্রমিস হ্যান্ডেলের জন্যই async আর await এর পরিচয় করিয়ে দেওয়া হয়েছে। যেখানেই আপনি এরকম অ্যাসিনক্রোনাস কোডকে সিনক্রোনাস আচরণ করাতে চান সেখানেই এগুলো ব্যবহার করতে পারবেন। তবে এখানে কিছু নিয়ম কানুন আছে। আপনাকে async এই কীওয়ার্ডটা ব্যবহার করতে হবে ফাংশনের সাথে। আপনি যে কোডগুলোকে সিনক্রোনাস আচরণ করাতে চাচ্ছেন সেগুলো সবগুলো একটা ফাংশনের ভিতরে ঢুকিয়ে সেই ফাংশনের নামের আগে জাস্ট এভাবে async কীওয়ার্ডটা লাগিয়ে দিবেনঃ

const promiseHandle = async() => {
   const data = await myPromise;
   console.log(data);
}

এখানে দেখুন লক্ষ্য করে আমি ঠিক এর পরের লাইনেই আমাদের প্রমিস থেকে আসা ডাটা প্রিন্ট করে দিয়েছি। হ্যা এখানেই async আর await এর ম্যাজিক। এটা আমাদের অ্যাসিনক্রোনাস কোডকে সিনক্রোনাস আচরণ করতে সাহায্য করে যাতে আমাদের আর কলব্যাকে হেলে পড়তে না হয়। আমরা একদম লাইন বাই লাইন ইন্সট্রাকশন দিয়েই ডাটা উদ্ধার করতে পারবো।

এখন যদি প্রমিস রিজেক্টেড হয় তাহলে? হ্যা তাহলে আমরা  try catch ব্লক দিয়েই আমরা আমাদের এই এরর হ্যান্ডল করতে পারবো।