天天看點

Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)

      小菜前幾天剛學習了 Future 實作異步操作的部分方法,主要包括構造方法和常用的靜态方法;小菜今天繼續學習 Future 其他知識和 async-await 方式實作異步操作;

Future 嵌套

      小菜在上篇部落格中未做 Future 嵌套嘗試,有很多場景需要多個異步處理,且每個異步都需要上個異步傳回的結果 then() 之後才可以繼續,此時可以用 Future 嵌套方式;但如果潛套方法較多可能會對今後的代碼維護造成一定影響,即常說到的 Callback hell;

_futureMoreThen() {
  Future.delayed(Duration(seconds: 3), () {
    return 'Future.delayed 3s!';
  }).then((val) {
    print('Future -> then(1) -> $val');
    return 'then 1';
  }).then((val) {
    print('Future -> then(2) -> $val');
    return 'then 2';
  }).then((val) {
    print('Future -> then(3) -> $val');
    return 'then 3';
  }).whenComplete(() => print('Future whenComplete!'));
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)
_futureMoreThen02() {
  Future.delayed(Duration(seconds: 3), () {
    return 'Future.delayed 3s!';
  }).then((val) {
    print('Future -> then(1) -> $val');
    return Future.delayed(Duration(seconds: 2), () {
      return 'Future.delayed 2s!';
    }).then((val) {
      print('Future -> then(2) -> $val');
      return Future.delayed(Duration(seconds: 2), () {
        return 'Future.delayed 2s!';
      }).then((val) {
        print('Future -> then(3) -> $val');
      });
    });
  }).whenComplete(() => print('Future whenComplete!'));
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)

async-await

      Future 也可以通過 async-await 實作異步操作;其使用場景通常是在多個 Future 串聯起來,多層級嵌套而導緻的 Callback hell,使用 async-await 實作異步;

async

      async 用來修飾的異步方法最終将傳回值封裝成 Future 對象;

await

      await 會把自動把該方法進入阻塞狀态,一直待任務執行完成并傳回對應值;

案例嘗試

      小菜先嘗試了基本的 async-await 用法;

(a.) 小菜未采用 async 和 await 關鍵詞,此時 Future.delayed() 傳回的是一個 Future 對象,不能同步的擷取傳回資料;

print(_function01());

_function01() {
  var result = Future.delayed(Duration(seconds: 3), () {
    return 'Future.delayed 3s!';
  }).then((val) => print('Function01 -> then() -> $val'))
    .whenComplete(() => print('Function01 -> whenComplete!'));
  return 'Function01 -> $result';
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)

(b.) 小菜僅添加了 async 關鍵詞,将該方法修飾為異步方法,依舊不能直接擷取傳回資料

print(_function01());

Future<String> _function02() async {
  var result = Future.delayed(Duration(seconds: 3), () {
    return 'Future.delayed 3s!';
  }).then((val) => print('Function02 -> then() -> $val'))
    .whenComplete(() => print('Function02 -> whenComplete!'));
  return 'Function02 -> $result';
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)

(c.) 小菜添加了 async 和 await 兩個關鍵詞,編譯器最終會将其轉化為一個 Promise(Future) 的調用鍊,可以待異步完成之後擷取傳回結果;此時 Future 不能設定 then() 回調方法等;

print(await _function03());

_function03() async {
  var result = await Future.delayed(Duration(seconds: 3), () {
    return 'Future.delayed 3s!';
  });
  return 'Function03 -> $result';
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)

(d.) 小菜嘗試隻用 await,此時提示 The await expression can only used in an async function,await 隻能用在 async 方法内部;

(e.) 采用 async-await 方式時,對于異常的捕獲,可以通過 Future.catchError() 來處理,還可以采用最常用的 try-catch-finally 方式,小菜簡單了解對應 then()-catchError()-whenComplete();

await _function04();

_function04(index) async {
  switch (index) {
    case 1:
      await Future.error(ArgumentError.notNull('Input')).catchError((val) => print('Function04 -> $val'));
      break;
    case 2:
      try {
        await Future.error(ArgumentError.notNull('Input'));
      } catch (e) {
        print('Function04 -> catch -> $e');
      } finally {
        print('Function04 -> Finally!');
      }
      break;
  }
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)

(f.) 針對多個 Future 嵌套導緻的 Callback hell,async-await 處理方式要簡潔一些;

await _functionThen();

_functionThen() async {
  await _itemThen01();
}

_itemThen01() async {
  await Future.delayed(Duration(seconds: 3), () {
    print('Future -> then(1) -> Future.delayed 3s!');
    return _itemThen02();
  });
}

_itemThen02() async {
  await Future.delayed(Duration(seconds: 2), () {
    print('Future -> then(2) -> Future.delayed 2s!');
    return _itemThen03();
  });
}

_itemThen03() async {
  await Future.delayed(Duration(seconds: 2), () {
    print('Future -> then(3) -> Future.delayed 2s!');
    return 'Future.delayed 2s!';
  }).whenComplete(() => print('Future whenComplete!'));
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)

小擴充

      小菜在嘗試 async-await 時還遇到 async,小菜在 bloc 狀态管理時使用時都是 async 和 Stream,小菜簡單了解一下相關差異;

async*

      async 也可以用于異步,方法前使用 async 關鍵字可以将該方法标記為異步生成器,傳回的是一個 Stream 對象,使用 yield 語句來傳遞值;

      對于 Stream 的使用,小菜之前有基本的了解,一般通過 skin 添加資料,通過 listen 進行資料監聽;

      yield 關鍵字會向 async* 聲明的一步生成器的輸出流添加一個值,有點類似 return,但不會終止函數;

_function06() async* {
  for (int i = 1; i <= 10; i++) {
    await Future.delayed(const Duration(seconds: 1));
    yield i;
  }
}           
await for (int num in _function06()) {
  print('current num = $num');
}           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)
_function06().listen((num) => print('current num = $num'));           
Flutter 91: 圖解 Dart 單線程實作異步處理之 Future (二)
Dart async-await 案例嘗試

      小菜對 Dart 異步的認知還不完全,接下來會繼續嘗試 isolate 以及 EventLoop 執行順序等;如有錯誤和遺漏請多多指導!

來源: 阿策小和尚

繼續閱讀