JavaScript এর অন্যতম পাওয়ারফুল দিক হল কত সহজে এটা asynchronous programming হ্যান্ডেল করে। ব্রাউজারের ল্যাঙ্গুয়েজ হিসেবে শুরু থেকেই JS এর user interaction যেমন ক্লিক কিংবা কি প্রেসিং ধরনের asynchronous আচরণ হ্যান্ডেল করার ক্ষমতা থাকার প্রয়োজন ছিল। শুরুতে এই কাজটা করা হত Event এর মাধ্যমে। Node Js event এর বিকল্প হিসেবে callback কন্সেপ্টটা জনপ্রিয় করে। কিন্তু asynchronous programming এর ব্যবহার যতই বাড়তে থাকল, event আর callback আর পাওয়ারফুল রইল না সবকিছু হ্যান্ডেল করার। এরই পরিপ্রেক্ষিতে আসে Promise.

# Asynchronous Programming

Single threaded ল্যাঙ্গুয়েজ হয়ার জন্য JS একই সময়ে অনেকগুলো কাজ(Piece of code) একসাথে execute করতে পারে না। JS engine একটি একটি করে কাজ সম্পাদন করে। একারণে এই কাজগুলোর কোনটির পর কোনটি execute হবে সেটা maintain করার জন্য কাজগুলো একটা Job Queue তে রাখা হয়। একটা কাজ যখন রেডি হয় তখন একে Job queue তে রাখা হয়। একটি কাজ শেষ হয়ে Job Queue তে রাখা পরের কাজটি execute হয়। এই ম্যানেজমেন্টটা Event Loop নামক JS engine এর একটি process দিয়ে সম্পাদন করা হয়।

# The Event Model

যখন user keyboard এর একটা বাটন/কি প্রেস করে তখন onClick এর মত event trigger করে। নিচের উদাহরণ দেখি।

let button = document.getElementById("my-btn");
  button.onclick = function(event) {
  console.log("Clicked");
};

এই কোড এ console.log(“Clicked”) execute হবে না যতক্ষণ না “button” click করা হয়। button.onClick এ assign করা ফাংশনটা Job Queue তে যুক্ত হয় এবং পূর্বের job গুলো execute হবার পর এটা execute হবে। এটা asynchronous programming এর সবচেয়ে ব্যাসিক form।

এধরনের সিম্পল কাজের জন্য event ঠিক আছে। কিন্তু এভাবে একের পর এক asynchronous call chain করা complicated। কারণ সবগুলো event এর জন্য event target ( এই উদাহরনে button) এর ট্রাক রাখা লাগে।

# The Callback Pattern

Node Js এসে asynchronous programming কে একধাপ আগায় নিয়ে যায় এর callback pattern এর মাধ্যমে। Callback প্যাটার্ন event-model এর মতই। পার্থক্য হল এখানে ফাংশন কলটা আরগুমেন্ট হিসেবে pass হয়।

readFile("example.txt", function(err, contents) {
  if (err) {
    throw err;
  }
  console.log(contents);
});
console.log("Hi!");

উপরের উদাহরনে, readFile() ফাংশনের কাজ হচ্ছে disk থেকে example.txt ফাইলটা পড়া এবং কমপ্লিট হলে callback (২য় আরগুমেন্ট) execute করা। যদি ফাইল পড়তে গিয়ে কোন error পায় তাহলে callback এর 'err' আরগুমেন্ট error object contain করে। অন্যথায় contnents আরগুমেন্ট ফাইলের কন্টেন্ট string হিসেবে কন্টেইন করে।

সুতরাং আমাদের কোড execute করা শুরু করলে readFile() যখন disk থেকে ফাইল পড়া শুরু করে তখন execution pause করে। ফলে console.log(“Hi”) সাথে সাথে execute হয়ে আউটপুট দেখায়। পরে যখন readFile() example.txt পড়া শেষ করে then সেটাconsole.log(contents) execute করে আউটপুট দেয়। এর মানে হল job queue তেreadFile() যাবার আগেই cosole.log(“Hi”) যায়।

# Chaining Multiple Calls

Event model এর তুলনায় callback প্যাটার্ন এ চেইনিং তুলনামূলক সহজ।

readFile("example.txt", function(err, contents) {
  if (err) {
    throw err;
  }

  writeFile("example.txt", function(err) {
    if (err) {
      throw err;
    }
    console.log("File was written!");
  });
});

এই উদাহরণে readFile() example.txt পড়া শেষ করে Job Queue তে job add করে যেকারণে যখন এই job execute করা হয় তখন writeFile() call করা হয় এরপর writeFile() তার job, Job Queue তে add করে।

এই প্যাটার্নটি খুবি কাজের, কিন্তু চিন্তা করা যাক যে আমরা একের পর এক ফাংশন কল add করছি। দ্রুতই এটা Callback Hell এ রুপ নেবে নিচের মত।

method1(function(err, result) {

    if (err) {
        throw err;
    }

    method2(function(err, result) {

        if (err) {
            throw err;
        }

        method3(function(err, result) {

            if (err) {
                throw err;
            }

            method4(function(err, result) {

                if (err) {
                    throw err;
                }

                method5(result);
            });

        });

    });

});

এভাবে nesting করা কোড বুঝতে যেমন পেইন তেমনি ডিবাগ করাও কঠিন। Callback আরো কিছু প্রব্লেম দেয়, যেমন যদি আমি দুটি asynchronous operation একি সময়ে চালাতে চাই এবং আমাকে তখনি নটিফাই করবে যখন দুটোই কমপ্লিট হবে। কিংবা যদি দুটো asynchronous operation চালানো হল, প্রথম যেটা কমপ্লিট হবে শুধুমাত্র সেই রেসাল্টটাই নিব। এসব ক্ষেত্রে আমাদের multiple callback এবং clean up operations নিয়ে কাজ করতে হবে। Promise এসব সিটুয়েশন দারুনভাবে ইম্প্রুভ করে। Promise নিয়ে লিখব পরের পর্বে।

# Encouraged From

Understanding ES6 by Nicholas C. Zakas (opens new window)