February 08, 2024 / 4 min read

Understanding Asynchronous JavaScript: Callbacks, Promises, and Async/Await

JavaScript

⚓︎What is Asynchronous Programming?

Synchronous Programming မှာ operations တွေကို တစ်ခုပြီးမှ တစ်ခု အစဉ်လိုက် လုပ်ဆောင်သွားပါတယ်။ ဒါပေမယ့် Asynchronous Programming မှာတော့ အချို့ operations တွေကို တခြား operations တွေနဲ့ လွတ်လပ်စွာ လုပ်ဆောင်နိုင်ပါတယ်။ ဒီလိုလုပ်ဆောင်နိုင်တာကို Non-blocking I/O လို့လည်း ခေါ်ပါတယ်။

Synchronous vs Asynchronous

  1. Synchronous Programming:

    • Operations တွေကို တစ်ခုပြီးမှ တစ်ခု အစဉ်လိုက် လုပ်ဆောင်ပါတယ်။
    • ဥပမာ: ပထမ operation ပြီးမှ ဒုတိယ operation ကို စလုပ်ပါတယ်။
    • ပထမ operation က ကြာနေရင် ဒုတိယ operation ကို စလုပ်လို့မရပါဘူး။
  2. Asynchronous Programming:

    • Operations တွေကို တစ်ခုနဲ့တစ်ခု လွတ်လပ်စွာ လုပ်ဆောင်နိုင်ပါတယ်။
    • ဥပမာ: ပထမ operation ကို စလုပ်ပြီး၊ သူပြီးမှာကို မစောင့်ဘဲ ဒုတိယ operation ကို ချက်ချင်းစလုပ်နိုင်ပါတယ်။
    • ပထမ operation က ကြာနေရင်တောင် ဒုတိယ operation ကို စလုပ်လို့ရပါတယ်။

အထူးသဖြင့် ဒီ operations တွေမှာ အသုံးပြုတာများပါတယ်။

  • API ကနေ data လှမ်းယူတာ

    • ဥပမာ - ဝက်ဘ်ဆိုက်တစ်ခုကနေ သတင်းအချက်အလက်တွေ လှမ်းယူတာမျိုးတွေ။
  • File တွေဖတ်တာ

    • ဥပမာ - ကွန်ပျူတာထဲက file တစ်ခုကို ဖတ်ပြီး data တွေ ထုတ်ယူတာမျိုးတွေ။
  • ကြာရှည်စွာ လုပ်ဆောင်ရတဲ့ တွက်ချက်မှုတွေ လုပ်တာ

    • ဥပမာ - ဂဏန်းတွေ အများကြီးကို တွက်ချက်တာမျိုးတွေ။

⚓︎Callbacks

Callback ဆိုတာ function တစ်ခုကို နောက် function တစ်ခုမှာ argument အဖြစ် ပေးလိုက်ပြီး၊ ပထမ function ပြီးသွားတဲ့အခါမှာ လုပ်ဆောင်ခိုင်းတာပါ။ ဒါက Asynchronous operations တွေကို ကိုင်တွယ်ဖြေရှင်းတဲ့ နည်းလမ်းတစ်မျိူးပါ။

Example of Callback:

function fetchData(callback) {
  setTimeout(() => {
    callback("Data fetched successfully");
  }, 2000); // 2 စက္ကန့်ကြာမှ callback function ကို ခေါ်မယ်ဆိုပြီး delay ခံထားတာပါ။
}
 
fetchData((message) => {
  console.log(message); // Output: Data fetched successfully
});

Explanation

  • fetchData function ကို ခေါ်လိုက်တဲ့အခါ၊ setTimeout က 2 စက္ကန့်စောင့်ပြီးမှ callback function ကို ခေါ်မှာဖြစ်ပါတယ်။
  • callback function ကို ခေါ်တဲ့အခါ၊ "Data fetched successfully" ဆိုတဲ့ message ကို ပြန်ပေးမှာပါ။

Drawbacks of Callbacks:

  • Callback Hell: Asynchronous operations တွေ အများကြီး ထပ်နေရင် code တွေက ဖတ်ရခက်ပြီး ထိန်းသိမ်းရခက်လာပါတယ်။
fetchData1((data1) => {
  fetchData2(data1, (data2) => {
    fetchData3(data2, (data3) => {
      console.log(data3);
    });
  });
});
  • Error Handling: Error တွေကို handle လုပ်ရတာ ပိုရှုပ်ထွေးလာပါတယ်။

⚓︎Promises

Promise ဆိုတာ Asynchronous operation တစ်ခု အောင်အောင်မြင်မြင်နဲ့ ပြီးစီးသွားတာလား / မပြီးစီးတာလားဆ်ိုတာကို ကိုယ်စားပြုတဲ့ object တစ်ခုပါ။ Promises တွေက Asynchronous code တွေကို ပိုပြီး ရှင်းလင်းစွာ ဖြေရှင်းနိုင်ပါတယ်။ Callback hell ကိုလဲ ရှောင်ရှားနိုင်မှာဖြစ်ပါတယ် ။

Callback Hell ဆိုတာဘာလဲ?

Callback Hell ဆိုတာ Asynchronous Programming မှာ Callback functions တွေကို အများကြီး ထပ်ပြီး သုံးရတဲ့အခါ ဖြစ်လာတဲ့ ပြဿနာတစ်ခုပါ။ ဒီပြဿနာကို Pyramid of Doom လို့လည်း ခေါ်ပါတယ်။ Callback functions တွေ အများကြီး ထပ်နေတဲ့အခါ code တွေက ဖတ်ရခက်ပြီး ထိန်းသိမ်းရခက်လာပါတယ်။

ဥပမာအနေနဲ့ အောက်က code ကို ကြည့်ပါ။

fetchData1((data1) => {
  fetchData2(data1, (data2) => {
    fetchData3(data2, (data3) => {
      fetchData4(data3, (data4) => {
        console.log("Final Data:", data4);
      });
    });
  });
});

A promise has three states:

  • Pending: Initial state, neither fulfilled nor rejected.
  • Fulfilled: The operation completed successfully.
  • Rejected: The operation failed.

Example of a Promise:

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = true;
      if (success) {
        resolve("Data fetched successfully");
      } else {
        reject("Failed to fetch data");
      }
    }, 2000);
  });
}
 
fetchData()
  .then((message) => console.log(message)) // Output: Data fetched successfully
  .catch((error) => console.log(error)); // Output: Failed to fetch data (if error occurs)

Explanation

  • fetchData - function က Promise တစ်ခုကို return ပြန်ပါတယ်။
  • resolve ကို ခေါ်ရင် .then() ထဲက function ကို execute လုပ်ပါတယ်။
  • reject ကို ခေါ်ရင် .catch() ထဲက function ကို execute လုပ်ပါတယ်။

Benefits of Promises:

  • Chaining: Promises တွေကို .then() နဲ့ .catch() တွေနဲ့ အသုံးပြုနိုင်ပါတယ်။ ဒါကြောင့် code တွေကို ပိုပြီး ဖတ်ရလွယ်ကူစေပါတယ်။
  • Error Handling: Promises တွေက .catch() နဲ့ error handling ကို ပိုကောင်းမွန်စွာ လုပ်ဆောင်နိုင်ပါတယ်။

⚓︎Async/Await

Async/Await ဆိုတာ ES2017 မှာ မိတ်ဆက်ပေးလိုက်တဲ့ syntactic sugar တစ်ခုပါ။ Promises တွေပေါ်မှာ အခြေခံထားပါတယ်။ Asynchronous code တွေကို Synchronous code လိုမျိုး ရေးသားနိုင်ပါတယ်။ ဒါကြောင့် ဖတ်ရလွယ်ကူပြီး ထိန်းသိမ်းရလွယ်ကူစေပါတယ်။

  • async: Function က အမြဲတမ်း Asynchronous ဖြစ်ပြီး Promise တစ်ခုကို အလိုအလျောက် return ပြန်ပေးပါတယ်။
  • await: async function တစ်ခုရဲ့ execution ကို Promise ပြီးဆုံးတဲ့အထိ ခေတ္တရပ်နားထားပါတယ်။

Example of Async/Await:

async function fetchData() {
  try {
    const data = await new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("Data fetched successfully");
      }, 2000); // 2 စက္ကန့်ကြာမှ resolve ကို ခေါ်ပါမယ်။
    });
    console.log(data); // Output: Data fetched successfully
  } catch (error) {
    console.log(error); // Error ဖြစ်ရင် ဒီမှာ handle လုပ်ပါမယ်။
  }
}
 
fetchData();

Explanation

  • fetchData function ကို async keyword နဲ့ သတ်မှတ်ထားပါတယ်။
  • await keyword က Promise ပြီးဆုံးတဲ့အထိ စောင့်ပေးပါတယ်။
  • try/catch ကို အသုံးပြုပြီး error တွေကို handle လုပ်ပါတယ်။

Benefits of Async/Await:

  • Readability: Code တွေက Synchronous code လိုမျိုး ဖြစ်နေတာကြောင့် လိုက်ဖတ်ရတာ ပိုလွယ်ကူပါတယ်။
  • Error Handling: Error တွေကို try/catch နဲ့ ကိုင်တွယ်နိုင်ပါတယ်။

⚓︎Conclusion

Asynchronous Programming ကို နားလည်ထားရင် JavaScript မှာ ပိုမိုထိရောက်စွာ code တွေရေးသားနိုင်မှာပါ။ Callbacks, Promises, နဲ့ Async/Await တို့ကို သေချာလေ့လာထားရင် Asynchronous code တွေကို ပိုမိုကျွမ်းကျင်စွာ အသုံးပြုနိုင်မှာပါ။

Happy Coding! 🎉