API call တွေမှာ async/await သုံးထားတယ်။ Screen ကိုလည်း ဆက်နှိပ်လို့ရတယ်။ ဒါပေမယ့် data စုံအောင်ရဖို့ စောင့်နေရတုန်းပဲ။

ဒီလိုဖြစ်တဲ့အခါ API တစ်ခုချင်းစီ နှေးနေတာလား၊ ကိုယ့် code က တစ်ခုပြီးမှတစ်ခု ခေါ်နေတာလားဆိုတာ ခွဲကြည့်ဖို့လိုတယ်။

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

Async ဖြစ်တာနဲ့ အလုပ်အားလုံး အတူစတာ မဟုတ်ဘူး

Dart မှာ await က လက်ရှိ function ရဲ့ နောက်တစ်ဆင့်ကို Future ပြီးတဲ့အထိ စောင့်စေတယ်။ အဲဒီ Future မပြီးသေးတဲ့အချိန်မှာ event loop က တခြားအလုပ်တွေကို ဆက်လုပ်နိုင်တယ်။ ဒါပေမယ့် await အောက်က code ကိုတော့ အလိုအလျောက် ကျော်မလုပ်ပေးဘူး။ Dart async/await လမ်းညွှန်

Home screen တစ်ခုမှာ profile နဲ့ announcements ကို ပြချင်တယ်ဆိုပါစို့။ ဒီဥပမာမှာ request နှစ်ခုက တစ်ခုရဲ့ result ကို တစ်ခုမလိုဘူးလို့ ယူထားမယ်။

ရှင်းအောင် နှစ်ခုလုံးကို String ပြန်ပေးတဲ့ demo function တွေအဖြစ် ရေးထားတယ်။ တကယ့် app မှာတော့ ကိုယ့် data model တွေကို သုံးနိုင်တယ်။

Future<List<String>> loadSequentially() async {
  final profile = await fetchProfile();
  final announcements = await fetchAnnouncements();
  return [profile, announcements];
}

ဒီ code မှာ fetchProfile() ပြီးမှ fetchAnnouncements() ကို စခေါ်တယ်။ Function နှစ်ခုလုံးက asynchronous ဖြစ်ပေမယ့် ခေါ်တဲ့အစီအစဉ်က တစ်ခုပြီးမှတစ်ခု ဖြစ်နေတယ်။

Profile အတွက် 600 ms၊ announcements အတွက် 900 ms ကြာတယ်လို့ ဥပမာယူရင် နှစ်ခုလုံးရဖို့ 1,500 ms လောက် စောင့်ရမယ်။ ဒီကိန်းဂဏန်းတွေက ရှင်းပြဖို့ သတ်မှတ်ထားတဲ့ delay တွေပါ။ Production API က တိုင်းထားတဲ့အချိန်တွေ မဟုတ်ပါဘူး။

တစ်ခုကိုတစ်ခု မစောင့်ရလည်း ရတယ်ဆိုရင်

ဒီဥပမာမှာ announcements ကို စခေါ်ဖို့ profile ပြီးအောင် စောင့်စရာမလိုဘူး။ အဲဒါကြောင့် request နှစ်ခုလုံးကို စလုပ်ပြီးမှ result တွေကို စုပြီး စောင့်နိုင်တယ်။

Future<List<String>> loadConcurrently() {
  return Future.wait<String>([
    fetchProfile(),
    fetchAnnouncements(),
  ]);
}

List ထဲမှာ function နှစ်ခုကို ခေါ်လိုက်တဲ့အချိန်မှာ အလုပ်နှစ်ခု စတင်တယ်။ ပထမ request ပြီးအောင် မစောင့်ဘဲ ဒုတိယ request ကို ဆက်ခေါ်တာပါ။ Future.wait က အဲဒီ Future တွေရဲ့ result ကို စုပေးတယ်။

နှစ်ခုလုံး အောင်မြင်ရင် result list က input အစီအစဉ်အတိုင်း ပြန်လာတယ်။ ဘယ် request က အရင်ပြီးလဲဆိုတာနဲ့ မဆိုင်ဘူး။ ဒီဥပမာမှာ results[0] က profile၊ results[1] က announcements ဖြစ်မယ်။ Future.wait API

Sequential နှင့် concurrent request များ၏ စောင့်ဆိုင်းချိန်ကို နှိုင်းယှဉ်ထားသော timeline

သတ်မှတ်ထားတဲ့ delay တွေနဲ့ ရှင်းပြထားတဲ့ timeline ပါ။ Network၊ server နဲ့ scheduling ကြောင့် တကယ့်အချိန်တွေ ကွာနိုင်တယ်။

ဒီလို အတူစလိုက်ရင် နှစ်ခုလုံးရဖို့ 900 ms လောက်ပဲ လိုတော့တယ်။ Request တစ်ခုချင်းစီ ပိုမြန်သွားတာ မဟုတ်ဘူး။ Announcements ကို စခေါ်ဖို့ profile ပြီးတဲ့အထိ စောင့်ခဲ့ရတဲ့အချိန်ကို ဖယ်လိုက်တာပါ။

ဒီတွက်ချက်ပုံက အလုပ်နှစ်ခု အမှန်တကယ် ထပ်တူလုပ်နိုင်တဲ့အခြေအနေအတွက်ပါ။ Server က request တွေကို တန်းစီလုပ်နေတာ၊ connection limit ရှိနေတာမျိုးဆိုရင် အချိန်က ဒီအတိုင်း မဖြစ်နိုင်ဘူး။

တချို့ Await တွေကတော့ လိုအပ်တယ်

ဒုတိယ request အတွက် ပထမ result ကို လိုနေတယ်ဆိုရင် စောင့်ရမယ်။ ဥပမာ login ပြီးမှ ရလာတဲ့ token နဲ့ protected data ကို ခေါ်ရတဲ့အခြေအနေမျိုးပါ။

// Sketch only: signIn and fetchProtectedData are app-specific.
final session = await signIn();
final data = await fetchProtectedData(session.token);

ဒီနေရာမှာ await က မလိုအပ်တဲ့အတားအဆီး မဟုတ်ဘူး။ နောက်အလုပ်ကို စဖို့ လိုတဲ့အချက်အလက်ကို စောင့်နေတာပါ။

တစ်ခုချင်းစီ ကြည့်ရမယ့်မေးခွန်းက “ဒီ request ကို စလုပ်ဖို့ အရင် result တကယ်လိုသလား” ဆိုတာပဲ။ Result မလိုပေမယ့် လုပ်ဆောင်ရမယ့်အစီအစဉ် သတ်မှတ်ထားတာ၊ shared resource တစ်ခုကို ပြိုင်သုံးလို့မရတာမျိုးလည်း ရှိနိုင်တယ်။

Request တစ်ခု Fail ဖြစ်ရင် ဘာလုပ်မလဲ

အလုပ်တွေကို အတူစလိုက်ပြီးရင် error ဖြစ်တဲ့အခါ ဘာလုပ်မလဲဆိုတာလည်း စဉ်းစားဖို့လိုတယ်။

Future.wait မှာ default eagerError: false ဖြစ်တယ်။ Future တစ်ခု fail ဖြစ်ရင် ကျန်တာတွေ ပြီးတဲ့အထိ စောင့်ပြီးမှ ပထမ error နဲ့ ပြန်ပြီးတယ်။ အောင်မြင်တဲ့ result တွေပါတဲ့ list ကို ပြန်မပေးဘူး။

eagerError: true သုံးရင် ပထမ error ရတာနဲ့ စောစောပြန်ပြီးနိုင်တယ်။ ဒါပေမယ့် စလုပ်ထားပြီးသား request တွေကို အလိုအလျောက် cancel မလုပ်ပေးဘူး။ Future.wait error behavior

ဒီဥပမာကို screen တစ်ခုမှာ သုံးမယ်ဆိုရင် ရွေးစရာက နှစ်မျိုးရှိတယ်။

  • နှစ်ခုလုံးမရရင် screen ကို မပြချင်ဘူးဆိုရင် loading နဲ့ error state ကို တစ်စုတည်း ထိန်းနိုင်တယ်။
  • Profile ရရင် အရင်ပြပြီး announcements ကို သီးခြားစောင့်လို့ရတယ်ဆိုရင် section တစ်ခုစီရဲ့ loading နဲ့ error state ကို ခွဲထားနိုင်တယ်။

ဒုတိယပုံစံမှာတော့ အထက်က Future.wait တစ်ခုတည်းကို စောင့်တဲ့ code ထက် result နဲ့ error ကို သီးခြားလက်ခံတဲ့ပုံစံ လိုမယ်။ Partial content ပြလို့ရမရကို screen ရဲ့လိုအပ်ချက်နဲ့အညီ ရွေးဖို့ပါ။

Flutter မှာ loading request ကို build() ခေါ်တိုင်း အသစ်စမနေဖို့လည်း လိုတယ်။ FutureBuilder သုံးရင် Future ကို initState() လို သင့်တော်တဲ့နေရာမှာ ပြင်ဆင်ထားပြီး၊ dependency ပြောင်းတဲ့အချိန်မှ ပြန်စဖို့ စဉ်းစားနိုင်တယ်။ FutureBuilder လမ်းညွှန်

Async က CPU အလုပ်ကို Background ပို့ပေးတာ မဟုတ်ဘူး

နောက်ထပ် ခွဲသိထားဖို့လိုတာတစ်ခုရှိတယ်။ Function မှာ async ထည့်လိုက်ရုံနဲ့ JSON အကြီးကြီး parse လုပ်တာလို CPU အလုပ်တွေက တခြား isolate ပေါ်ကို အလိုအလျောက် မရွှေ့သွားဘူး။ Main isolate မှာ synchronous အလုပ်ကြာနေရင် UI ကို တားနေနိုင်သေးတယ်။

ဒီဆောင်းပါးရဲ့ ဥပမာက I/O စောင့်နေချိန်တွေကို ထပ်တူလုပ်နိုင်အောင် ပြင်တာပါ။ CPU အလုပ်နှေးနေရင် profile လုပ်ပြီး bottleneck ကိုရှာဖို့၊ လိုအပ်ရင် ကိုယ့် platform နဲ့သင့်တော်တဲ့ isolate သို့မဟုတ် worker နည်းလမ်းကို စဉ်းစားဖို့လိုတယ်။ Concurrency in Dart

ပြင်ပြီးရင် တိုင်းကြည့်မယ်

အရင်ဆုံး request တစ်ခုချင်းစီရဲ့ start နဲ့ finish အချိန်ကို မှတ်ကြည့်နိုင်တယ်။ နောက်ပြီး screen မှာ လိုတဲ့ data စုံတဲ့အချိန်နဲ့ user စသုံးနိုင်တဲ့အချိန်ကို ခွဲကြည့်မယ်။

Network နဲ့ cache အခြေအနေတွေကြောင့် result က ကွာတတ်လို့ run တစ်ကြိမ်တည်းနဲ့ မဆုံးဖြတ်သင့်ဘူး။ တူညီတဲ့အခြေအနေမှာ ထပ်စမ်းပြီး error ဖြစ်တဲ့ case ကိုလည်း စစ်ကြည့်ဖို့လိုတယ်။

Request အနည်းငယ်ကို အတူခေါ်လို့ အဆင်ပြေတယ်ဆိုပြီး အများကြီးကို တစ်ပြိုင်နက် စမခေါ်သင့်ဘူး။ Server က လက်ခံနိုင်တဲ့ပမာဏနဲ့ resource အသုံးပြုမှုကို ကြည့်ပြီး တစ်ချိန်တည်း ဘယ်နှခုအထိ လုပ်မလဲဆိုတာ ကန့်သတ်ဖို့ လိုနိုင်တယ်။

Screen နှေးနေတယ်ဆိုရင် async ပါမပါ ကြည့်ရုံနဲ့ မလုံလောက်ဘူး။ ဘယ်အလုပ်က ဘယ်အလုပ်ကို စောင့်နေလဲဆိုတာပါ ကြည့်ဖို့လိုတယ်။ အဲဒီထဲမှာ တကယ်လိုအပ်တဲ့စောင့်ဆိုင်းမှု ရှိသလို၊ ဖယ်လို့ရတဲ့စောင့်ဆိုင်းမှုလည်း ရှိနိုင်တယ်။


ကိုယ်တိုင် စမ်းကြည့်ရန်

Runnable Dart demo — Future.delayed နဲ့ I/O စောင့်ချိန်ကို သရုပ်ပြထားတာပါ။ Network request မပို့ပါဘူး။ File ကို download လုပ်ပြီး Dart SDK ရှိတဲ့စက်မှာ dart async_demo.dart နဲ့ run နိုင်တယ်။