Dart Programming

Dart အခြေခံများ Part 1 (Futures)

မိတ်ဆက်

Dart Programming Language ရဲ့ အခြေခံတွေကို လေ့လာကြပါမယ်။ ဒါပေမယ့် Flutter မှာ အသုံးပြုနေတဲ့ Dart Programming ပုံစံကို အဓိက လေ့လာမှာ ဖြစ်ပါတယ်။ Flutter အနေနဲ့ Cross-platform Mobile နဲ့ Web Application တွေ တည်ဆောက်ရမှာ Dart Programming Language ကို အသုံးပြုပါတယ်။ ဒီဆောင်းပါတွေမှာတော့ Dart Programming Language ရဲ့ Feature တွေထဲက နှစ်ခုကို ဖော်ပြမှာ ဖြစ်ပါတယ်။

Futures: Asynchronous Programming with Dart

Futures ဆိုတာကတော့ Future Objects တွေကို ခေါ်တာ ဖြစ်ပါတယ်။ Asynchronous Operations တွေက ထွက်လာတဲ့ Result တွေကို စောင့်ယူဖို့အတွက် ဖြစ်ပါတယ်။ Asynchronous Operation တွေဆိုတာကတော့ Main Thread ကို မထိပါဘူး။ အချိန်တစ်ခုအထိ စောင့်ပြီးမှ Result ပြန်ထုတ်ပေးပါတယ်။ ဥပမာ – ကျွန်တော်တို့ API ကနေ Data တွေ ယူနေတယ်ဆိုပါစို့။ အချက်အလက်တွေ ယူနေတာကို အသုံးပြုသူကို ထိုင်စောင့်ခိုင်းမယ်ဆိုရင် အသုံးပြုသူက နှစ်သက်မှာ မဟုတ်ပါဘူး။ အဲဒီအတွက် သူသုံးစရာရှိတာကို ဆက်သုံးပြီး နောက်ကွယ်ကနေ အချက်အလက်တွေ ရယူဖို့ လိုတယ်ဆိုရင် Asynchronous Operation တွေကို အသုံးပြုရပါတယ်။ 

Asynchronous Operations တွေက ထွက်လာတဲ့ Result တွေက ပြန်လာတဲ့အခါ  Future Object အနေနဲ့ ပြန်လာပါတယ်။ ကျွန်တော်တို့ Android Kotlin မှာဆိုရင် Coroutines နဲ့ ပုံစံဆင်ပါတယ်။ Future<T> ပုံစံနဲ့ သုံးရပါတယ်။ အချိန်ယူရတဲ့ Data တွေကို ရယူတဲ့အခါ အသုံးပြုနိုင်ပါတယ်။

Asynchronous Operations တွေကို Dart နဲ့ သုံးမယ်ဆိုရင် နှစ်နည်းသုံးနိုင်ပါတယ်။

  1. Await နဲ့ Async ကို သုံးတာ
  2. Future API ကို အသုံးပြုတာ

await and async

await နဲ့ async ကို တွဲသုံးပါတယ်။ အချိန်စောင့်ရမယ့် အလုပ်တွေကို သုံးတော့မယ်ဆိုရင် async နဲ့ တွဲသုံးပါတယ်။ ကျွန်တော်တို့ နမူနာ ရေးကြည့်ရအောင်

import 'dart:async';

const data = "I'm expansive data";

Future<void> makeDataCall() async {
  var data = await getData();
  print(data);
}

String getData() {
  return data;
}

void main(List<String> args) {
  makeDataCall();
}

makeDataCall() က Asynchronous Function ဖြစ်ပါတယ်။ စောင့်ရမယ့် အလုပ်တွေအတွက်ပါ။ ပြီးရင် အတွင်းမှာ await getData() ဆိုပြီး သုံးပါတယ်။ getData() ကတော့ Expensive Function လို့ခေါ်တဲ့ စောင့်ရမယ့် အလုပ်ဖြစ်ပါတယ်။

Error Handling (try/catch block)

Error Handling အတွက် try catch block နဲ့ သုံးလို့ရပါတယ်။ ဒါကတော့ asynchronous ရော synchronous  မှာရော try catch သုံးတာ အတူတူပါပဲ။ ကျွန်တော်တို့ နမူနာရေးကြည့်ရအောင်

import 'dart:async';

const data = "I'm expansive data";

Future<void> makeDataCall() async {
  try {
    var data = await getData();
    throw Exception(
      "Error occurred in fetching data"
    );
  } catch(e) {
    print(e.toString());
  }
  
  
  print(data);
}

String getData() {
  return data;
}

void main(List<String> args) {
  makeDataCall();
}

လုပ်ငန်းဆောင်တာများကို အစဉ်လိုက် ပြုလုပ်စေခြင်း

ကျွန်တော်တို့ Android Work Manager မှာဆိုရင် Task A နဲ့ Task B ပြီးမှာ Task C လုပ်မယ် စသည်ဖြင့် Function တွေကို စီလို့ရပါတယ်။ အဲဒီလိုပုံစံမျိုးကို Dart မှာလဲ လုပ်လို့ရပါတယ်။ ဥပမာ – Categories တွေနဲ့ Authors တွေကို ယူပြီးမှာ Posts တွေကို ယူသလိုမျိုးဆိုရင် sequencing function calls ကို အသုံးပြုနိုင်ပါတယ်။ ကျွန်တော်တို့ နမူနာ ရေးကြည့်ရအောင်

import 'dart:async';

const data = "I'm expansive data";

void getDataA() {
  print("dataA");
}

void getDataB() {
  print("dataB");
}

String getDataC() {
  return "dataC";
}

void printMyData(String data) {
  print(data);
}

main() async {
  await getDataA();
  await getDataB();
  printMyData(await getDataC());
}

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

Future API

Future API ကတော့ Async Await ကို သုံးတာပါပဲ။ ရေးသားပုံနည်းနည်း ကွာသွားပါတယ်။ ရေးရတာ ပိုပြီး ရှင်းလင်းလွယ်ကူပါတယ်။ နမူနာရေးကြည့်ရအောင်

import 'dart:async';

const data = "I'm expansive data";

Future<String> makeDataCall() async {
  var data = await getData();
  return data;
}

String getData() {
  return data;
}

void main() {
  var theFurture = makeDataCall();
  theFurture.then((value){
      print(value);
  });
}

အကယ်၍ Future က တစ်ခုမှ return မပြန်ဘူးဆိုရင်တော့ အောက်က အတိုင်း ရေးနိုင်ပါတယ်။

import 'dart:async';

const data = "I'm expansive data";

Future<void> makeDataCall() async {
  var data = await getData();
  print(data);
}

String getData() {
  return data;
}

void main() {
  var theFurture = makeDataCall();
  theFurture.then((_){
      print("There's nothing to be printed here. Work is already done.");
  });
}

Future<void> အတွက် သုံးမယ်ဆိုရင် (_) ဆိုပြီး သုံးပေးရတာ သတိထားမိပါလိမ့်မယ်။

Error Handing in Future API

Future API မှာ Error Handling လုပ်ရတာ ပိုလွယ်ပါတယ်။ catchError() ဆိုပြီး သုံးပေးလို့ရပါတယ်။ 

import 'dart:async';

const data = "I'm expansive data";

// Future with String data is being returned.
// This function returns the instance of
// Future and not the actual data.

Future<String> makeDataCall() async {
  var data = await getData();
  throw Exception("Error occurred in making data call");
}

String getData() {
  return data;
}

void main() {
  var theFurture = makeDataCall();
  theFurture.then((value) {
    print(value);
  }).catchError((error){
    print(error);
  });
}

Future.wait()

Future.wait() ဆိုတာကိုတော့ အပေါ်မှာ ပြောခဲ့တဲ့အတိုင်း multiple asynchronous functions တွေကို တစ်ခုပြီးမှ တစ်ခု လုပ်စေချင်တဲ့အခါ အသုံးပြုနိုင်ပါတယ်။ ဥပမာ – 

import 'dart:async';

const data = "I'm expansive data";

String getData(data) {
  return data;
}

Future<String> getDataA() async {
  var data = await getData("dataA");
  return data;
}

Future<String> getDataB() async {
  var data = await getData("dataB");
  return data;
}

Future<String> getDataC() async {
  var data = await getData("dataC");
  return data;
}

void printMyData(List<String> data) {
  print(data);
}

main() async {
  await Future.wait([getDataA(), getDataB(), getDataC()])
    .then((List responses) => printMyData(responses))
    .catchError((error){});
}

References
Dart Futures

ယခုဆောင်းပါးအား ဤနေရာမှ ဘာသာပြန်ထားခြင်း ဖြစ်ပါသည်။ Creative Commons License အတိုင်း ဖြစ်ပါသည်။