Why Promises in JS

Wai Lin Kyaw
3 min readJan 20, 2021

Promises လို့ ပြောလိုက်တာနဲ့ JavaScript သမားတွေထဲ မသိတဲ့သူ မရှိသလောက်ပဲ။ နေ့တိုင်းလည်း သုံးနေကြရတာ။ ဒါပေမဲ့ promises တွေ ဘာ့ကြောင့် လိုသလဲ။ ဘယ်လို ပြသနာတွေ အတွက် design လုပ်ထားသလဲဆိုတာတွေ သိဖို့လိုပါတယ်။

Promises မတိုင်ခင် JS မှာ async အတွက်ဆိုရင် callbacks တွေသုံးရတယ်။ callback တွေမှာ အဓိက ပြသနာက inversion of control လို့ခေါ်တဲ့ callback function တစ်ခုရဲ့ execution ကို main program ကနေ control လုပ်ခွင့်မရတာပါပဲ။ နောက် callbacks တွေချည်းပဲ သုံးပြီး state management လုပ်တဲ့ အခါမှာလည်း တော်တော် ဒုက္ခရောက် ပါတယ်။ callback hell ဆိုပြီး ဒီအကြောင်းကို သပ်သပ်ရေးထားတာရှိပါတယ်။

Promises ရဲ့ သဘောက အခုမရှိသေးတဲ့ value တစ်ခုကို abstract လုပ်ထားတာပါ။ အဲ့ဒီ value ရောက်လာ ရှိလာတဲ့ အချိန်ကျ ဘာတွေ လုပ်မလဲဆိုတာ ကြိုပြီး ခိုင်းထားလို့ ရတယ်။ အခုမရှိသေးဘူး နောင်တစ်ချိန် ရှိလာမယ်ဆိုတဲ့ သဘော။ future value လို့ပြောရင်ရတယ်။

future value ကို ဥပမာ ပေးရမယ်ဆိုရင် coffee တစ်ဆိုင်ကို သွားမယ်၊ ပြီးရင် ကောင်တာမှာ coffee တစ်ခုခု cappuccino တစ်ခွက်ပေးပါလို့မှာလိုက်မယ်။ ဒီတော့ value တစ်ခု (cappuccino) ပြန်ပေးဖို့ request စလုပ်တယ်ပေါ့။ ကျသင့်ငွေလည်း ရှင်းလိုက်မယ်။ ဒါပေမဲ့ ‌‌‌ရောင်းတဲ့သူက ခုချက်ချင်းတော့ မရသေးဘူး ခဏစောင့် ရမယ်ဆိုပြီး ဖြတ်ပိုင်းလေး တစ်ခု ပြန်ပေးမယ်။ အဲ့ပေါ်မှာ order number လည်း ပါမယ်ပေါ့။ ဒီ order number နဲ့ ဖြတ်ပိုင်း ရှိရင် အချိန်ခဏ‌စောင့် ပြီးတာနဲ့ မှာထားတဲ့ coffee ( value တစ်ခု ) ကိုတော့ရမှာပဲ။

ဒီတော့ ကိုယ်က တစ်နေရာရာမှာ ထိုင်စောင့် နေမယ်။ စောင့်နေရင်းနဲ့ coffee ရရင်တော့ စာလေးဘာလေး ထိုင်ဖတ်ရင်းနဲ့ အေးအေးဆေး‌ဆေး သောက်မယ်လို့တွေးနေမယ် ( coffee မရသေးပေမဲ့ )။ သူငယ်ချင်း တစ်‌‌ယောက်ယောက်ကို ‘ငါတော့ coffee မှာထားတယ်၊ တူတူ လာသောက်ပါလား’ စသည်ဖြင့် မရသေးတဲ့ coffee ( value တစ်ခု ) နဲ့ ပက်သက်ပြီး coffee ရလာရင် ဘယ်လိုသောက်မယ် ဘာတွေလုပ်မယ် ( operations တွေ ) ကြိုစဉ်းစားထားလို့ရပြီ။ ဒါနဲ့ ကောင်တာကနေ ကိုယ့် order number ကိုလှမ်းအော်လိုက်တယ်ဆိုပါစို့။ ‌အဲ့တော့ order number လေးကိုင်ပြီး မှာထားတဲ့ နေရာသွားမယ်၊ ဒါနဲ့ ‌ရောင်းတဲ့လူက order number ပြ၊ ဒီမှာ coffee လို့ဆိုရင် future value က ready ( success ) ဖြစ်သွားပြီ။ လက်ထဲမှာ order number ရှိတဲ့အတွက် coffee ပြန်ရမယ်ပေါ့။ future value ဆိုတာလည်း ဒီသဘောပါ။ တကယ်လို့ cappuccino ကုန်နေတယ်ဆိုရင်တော့ ငွေပြန်အမ်းမယ် ( failure ) စသည်ဖြင့်ပေါ့။

ES6 မတိုင်ခင် Promises တွေကို JavaScript မှာ officially ထည့်မပေးခင် ကတည်းက promises library တွေ တော်တော်များများ ရှိနေပြီ။ Promises က JavaScript မှာ အစတည်းက ရှိတာတော့မဟုတ်ဘူး။ E programming language ကနေလာတာ။JavaScript language ကို standardize လုပ်နေတဲ့ TC39 committee မှာ Mark S.Miller ဆိုတဲ့ တစ်‌ယောက်ပါတယ်။ သူက E programming language ကို ရေးခဲ့တာ။ E programming language က concurrency model ကို deadlock free ဖြစ်အောင် event-loop တွေ promises ( not JS Promises ) တွေကို base ယူပြီး design ထုတ်ထားတာ။ E မှာ future ဆိုတာရှိတယ်။ ဒီ future က အချိန်တစ်ခုကြာရင် value တစ်ခုနဲ့ replace လုပ်ပစ်တာ။ ဒါပေမဲ့ value ရောက်မလာသေးရင်တောင် value ရှိတယ်လို့ ယူဆပြီး ပုံမှန် operations တွေ ကြိုလုပ်ထားလို့ရတယ်။ Promises တွေကလည်း E ကနေ ဒီ concept ကိုယူထားတာပါ။

Promises တွေမှာ ဘယ်အချိန် value ပြန်ရမလဲဆိုတဲ့ timing ကို ခဏမေ့ထားပြီးတော့ value နဲ့ပက်သက်တဲ့ operation တွေလုပ်လို့ရမှာပါ။ value ကို compose လုပ်ပေးတာ ထိန်းပေး ထားတာကို တွေ့ရမယ်။ Promises တွေရဲ့ လုပ်ဆောင်ချက်ကို functional programming အရ ကြည့်ရင် monad နဲ့ ဆင်တာတွေ့နိုင်ပါတယ်။

Promises တွေကို event listener တွေအဖြစ်လည်း မြင်ကြည့်လို့ရသေးတယ်။ ဥပမာ completion event ကို subscribe လုပ်ထားပြီး ဒီဖက်ကနေ listen လုပ်နေမယ်။ completion event က fire ဖြစ်တာနဲ့ event listener ကနေတစ်ဆင့် notified ဖြစ်မယ်။ ဒီတော့မှ လုပ်ခိုင်းချင်တာ ဆက်လုပ်ခိုင်းမယ်။ နောက် error event ကို subscribe လုပ်မယ်ဆိုလည်းရတယ် စသည်ဖြင့်ပေါ့။ ဒီနေရာမှာ ဆိုလိုချင်တာက promises တွေကို event listener လို့ပြောတာမဟုတ်ပါဘူး။ ပိုပြီး မြင်သာအောင် ယှဉ်ပြတာပါ။

Un-invert Inversion of Control

အစပိုင်းမှာ ပြောခဲ့တဲ့ callback ရဲ့ အဆိုးဆုံး ပြသနာဖြစ်တဲ့ inversion of control ဆိုတာက third party က library ကိုပဲဖြစ်ဖြစ်၊ ကို‌‌ယ်တိုင်ရေးထားတဲ့ utility တစ်ခုခုကိုပဲ ဖြစ်ဖြစ် callback တစ်ခု ပေးလိုက်တဲ့ အခါမှာ callback function ကိုတစ်ကြိမ်ပဲ run မှာလား ဘယ်နှစ်ကြိမ် run မှာလဲ၊ ဘယ်အချိန် run မှာလဲ၊ ဘယ်လို execute လုပ်မှာလဲ စတာတွေကို control လုပ်ခွင့်မရှိတော့ဘူး။ ဥပမာ shopping cart တွေမှာ checkout လုပ်တဲ့ feature ကို callback ထဲထည့်ပြီး တစ်နေရာရာကို argument pass လုပ်လိုက်မယ်။ callback ကို တစ်ကြိမ်မက 10 ကြိမ်လောက်သာ ထပ်ထပ် run နေရင် စဉ်းစား ကြည့်လိုက်ပါတော့။ user ဆီက bill ကို 10 — ကြိမ်လောက် ဖြတ်သွားမှာပါ။

Promises တွေမှာကျတော့ resolve နဲ့ reject ပဲရှိတယ်။ resolve ဖြစ်ရင်ဖြစ် မဖြစ်ရင် reject ဖြစ်မယ်။ success နဲ့ error condition နှစ်ခုထဲက တစ်ခုပဲ ဖြစ်မယ်ဆိုတာ အာမခံချက်‌ ပေးနိုင်တယ်။ နောက်ပြီးတော့ Promise တစ်ခါပဲ resolve လုပ်မယ်။ တစ်ကြိမ် resolve လုပ်ပြီးတာနဲ့ value ready ဖြစ်သွားပြီ။ နောက်ထပ်တစ်ကြိမ် resolve ထပ်လုပ်ချင် ပါတယ်ဆိုလည်း မရတော့ဘူး။ နောက်တစ်ခုက event listener လိုသဘောမျိုး .then ဆိုတဲ့ success ဖြစ်ခဲ့မယ်ဆိုရင် ဘာလုပ်မယ်၊ .error လို failure ဆိုရင် ဘာလုပ်မယ်ဆိုတာ ပြောလို့ရမယ်။ ဟိုးအရင် callback တွေနဲ့ချည်း သွားတာနဲ့ ဒီ event ဖြစ်ရင် ဒါလုပ်မယ်လို့ ပြောတာနှစ်ခုက တူသ‌ယောင်ရှိပေမဲ့ မတူပါဘူး။ ပြောရရင် control ကို ကိုယ့်လက်ထဲ ပြန်ထည့်ပေးတာပါ။inversion of control ကို uninvert လုပ်လိုက်တာပါ။ Promise ရဲ့ အဓိက အားသာချက်က ဒါပါပဲ။

ဒီနေရာမှာ တစ်ခု သတိထားရမှာက inversion of control က လုံးဝ အသုံးမဝင်တာ မဟုတ်ပါဘူး။ Framework တွေ design ချတဲ့ အခါမှာ inversion of control ကို ကောင်းကောင်း သုံးရပါတယ်။ library နဲ့ framework တွေကြားက အဓိက ကွာခြားချက် တွေထဲမှာ ဒီကောင်လည်း ပါတယ်။ ကိုယ်ပိုင် framework တွေဆောက်တာမျိုး၊ ရှိပြီးသားတွေ contribute လုပ်တာမျိုးဆိုရင် တွေ့ဖူးပါလိမ့်မယ်။

ES6 မတိုင်ခင်က Browser တွေ JS runtime တွေမှာ Event Loop တွေထည့်ပြီး implement လုပ်ကြပေမဲ့ ECMA spec မှာ official တော့မရှိသေးဘူး။ နောက် ES6 ကျတော့ promises တွေပါလာတယ်၊ Promises တွေက Event Loop နဲ့တွဲပြီး အလုပ်လုပ်တော့ Event Loop ပါ spec မှာတစ်ခါတည်း ပါလာတယ်။ Event Loop မှာ promises တွေအတွက် Job queue ကိုသုံးရတယ်။ microtask queue လို့လည်း သိကြတယ်။ Node.JS မှာကျတော့ Event-Loop အတွက် libUV ဆိုတဲ့ C နဲ့ရေးထားတဲ့ library တစ်ခုကိုသုံးတယ်။ ဒါပေမဲ့ Promises တွေ အတွက်ကျတော့ သူ့ထဲမှာပါတဲ့ queue တွေနဲ့တင် အဆင်မပြေတော့ Node.JS ကနေ နောက်ထပ် queue နှစ်ခု ထပ်ထည့်ရတယ်။ အသေးစိတ်ကိုတော့ Event Loop အကြောင်းနဲ့မှ တွဲကြည့်မှ ပို အဆင်ပြေမှာပါ။

အခုလောက်သိထားရင် promises တွေ ဘာလို့လိုအပ်လဲ သိနိုင်မယ်၊ သူ့နေရာနဲ့ သူ ကောင်းကောင်း အသုံးချနိုင်မယ်။ ဘယ်နေရာမှာ promises တွေသုံးသင့်လဲ သိသွား မယ်။ ဒီထဲမှာ promises ဆိုတာဘာလဲ၊ ဘာကြောင့်လိုအပ်လဲပဲ ရေးထားတာပါ။ သူ့ရဲ့ API နဲ့ နောက်ကွယ်မှာ ဘယ်လို အလုပ်လုပ်တယ်ဆိုတာတော့ မပါပါဘူး။

ဘာလို့ သုံးနေရမှန်း မသိတာထက်စာရင်တော့ တော်တော်လေးသိ သွားပါလိမ့်မယ်။

--

--