2.4、Dart語(yǔ)言基礎(chǔ):異步

學(xué)習(xí)筆記,旨在于快速入門(mén)和學(xué)習(xí)Dart,其中可能會(huì)有理解錯(cuò)誤,請(qǐng)指出,一起學(xué)習(xí)。

系列文章

2.1、Dart語(yǔ)言基礎(chǔ):變量、運(yùn)算符
2.2、Dart語(yǔ)言基礎(chǔ):函數(shù)與閉包
2.3、Dart語(yǔ)言基礎(chǔ):面向?qū)ο?/a>
2.4、Dart語(yǔ)言基礎(chǔ):異步
2.5、Dart語(yǔ)言基礎(chǔ):庫(kù)與包
...

一、概述

1、異步使用常見(jiàn)

  • 網(wǎng)絡(luò)獲取數(shù)據(jù)。
  • 讀寫(xiě)數(shù)據(jù)庫(kù)。
  • 讀寫(xiě)文件。

2、Dart語(yǔ)言中,異步相關(guān)的兩個(gè)對(duì)象Future or Stream。

Dart libraries are full of functions that return Future or Stream objects.

  • Future表示的是:?jiǎn)蝹€(gè)計(jì)算結(jié)果的異步封裝。
    A Future represents a computation that doesn’t complete immediately. Where a normal function returns the result, an asynchronous function returns a Future, which will eventually contain the result. The future will tell you when the result is ready.

  • Stream表示的是:多個(gè)序列化事件的異步封裝。其很像是一個(gè)異步的迭代器。
    A stream is a sequence of asynchronous events. It is like an asynchronous Iterable—where, instead of getting the next event when you ask for it, the stream tells you that there is an event when it is ready.

3、使用異步的兩種方式

  • 使用asyncawait/await for 語(yǔ)法糖。
  • 使用Future or Stream 相關(guān)APIs。

4、導(dǎo)入頭文件import 'dart:async';


二、Future

  • Future對(duì)象代表兩個(gè)狀態(tài):Uncompleted未完成、Completed完成(成功或者失敗)。
    A future represents the result of an asynchronous operation, and can have two states: uncompleted or completed.

1、常用接口

.then 狀態(tài)完成后回調(diào)
.delayed 延遲多少秒后,執(zhí)行回調(diào)
.whenComplete 無(wú)論成功和失敗都會(huì)執(zhí)行
.catchError 發(fā)生錯(cuò)誤,必須在then之后

  Future.delayed(Duration(seconds: 3), (){
    return 'Async: hello';
  }).then((value) => {
    print('then: recv ${value}')
  }).catchError((e){
    print('err: $e');
  }).whenComplete(() => {
    print('finish!')
  });

// 打印
// then: recv Async: hello
// finish!
  • .wait 阻塞函數(shù)執(zhí)行,等待wait函數(shù)里面的任務(wù)都完成,才會(huì)往下。
  Future.wait([
    Future.delayed(Duration(seconds: 3), (){
      return 'Hello';
    }),
    Future.delayed(Duration(seconds: 6), (){
      return ' World';
    })
  ]).then((value) => {
    print('Recv: $value')
  });

// 打印
// Recv: [Hello,  World]

2、多個(gè)Future對(duì)象

  • 鏈?zhǔn)酱?lián)多個(gè)異步方法
  Future result = costlyQuery(url);
  result.then((value) => expensiveWork(value))
  .then((_) => lengthyComputation())
  .then((_) => print('Done!'))
  .catchError((exception) {
    /* Handle exception... */
  }); 

// 等價(jià)于
try {
  final value = await costlyQuery(url);
  await expensiveWork(value);
  await lengthyComputation();
  print('Done!');
} catch (e) {
  /* Handle exception... */
}
  • Future.wait:等待所有Future執(zhí)行完,才繼續(xù)執(zhí)行。
Future<void> deleteLotsOfFiles() async =>  ...
Future<void> copyLotsOfFiles() async =>  ...
Future<void> checksumLotsOfOtherFiles() async =>  ...

await Future.wait([
  deleteLotsOfFiles(),
  copyLotsOfFiles(),
  checksumLotsOfOtherFiles(),
]);
print('Done with all the long steps!');

三、Stream

  • 主要用來(lái):異步處理 序列化的數(shù)據(jù)。例如,文件流、點(diǎn)擊事件流。

1、在循環(huán)中使用異步Using an asynchronous for loop。

void main(List<String> arguments) {
  // ...
  FileSystemEntity.isDirectory(searchPath).then((isDir) {
    if (isDir) {
      final startingDir = Directory(searchPath);
      startingDir.list().listen((entity) {
        if (entity is File) {
          searchFile(entity, searchTerms);
        }
      });
    } else {
      searchFile(File(searchPath), searchTerms);
    }
  });
}

// 等價(jià)于
Future<void> main(List<String> arguments) async {
  // ...
  if (await FileSystemEntity.isDirectory(searchPath)) {
    final startingDir = Directory(searchPath);
    await for (final entity in startingDir.list()) {
      if (entity is File) {
        searchFile(entity, searchTerms);
      }
    }
  } else {
    searchFile(File(searchPath), searchTerms);
  }
}
  • 注意:只有需要Streams的所有結(jié)果時(shí)候,才使用await for 。

2、常用接口

監(jiān)聽(tīng)流的數(shù)據(jù)或事件

  • .listen 所有值
submitButton.onClick.listen((e) {
  // When the button is clicked, it runs this code.
  submitData();
});
  • 單個(gè)數(shù)據(jù)
first()
last()
single()
// 單個(gè)數(shù)據(jù)前的攔截測(cè)試
firstWhere()
lastWhere()
singleWhere()
  • 一組流數(shù)據(jù)
skip()
skipWhile()
take()
takeWhile()
where()

流數(shù)據(jù)轉(zhuǎn)換(Transforming stream data)

  • transform()
var lines = inputStream
    .transform(utf8.decoder)
    .transform(const LineSplitter());

完成狀態(tài)

  • 成功 .onDone
  • 錯(cuò)誤 . onError

3、Stream 和 Future 的區(qū)別點(diǎn)

  • Stream和Future 不同的是,它可以接收多個(gè)異步操作的結(jié)果(成功或失敗)。 也就是說(shuō),在執(zhí)行異步任務(wù)時(shí),可以通過(guò)多次觸發(fā)成功或失敗事件來(lái)傳遞結(jié)果數(shù)據(jù)或錯(cuò)誤異常。

  • Stream 常用于會(huì)多次讀取數(shù)據(jù)的異步任務(wù)場(chǎng)景,如網(wǎng)絡(luò)內(nèi)容下載、文件讀寫(xiě)等。

  Stream.fromFutures([
    Future.delayed(Duration(seconds: 1), (){
      return 'result 1';
    }),
    Future.delayed(Duration(seconds: 2), (){
      throw AssertionError('sorry!');
    }),
    Future.delayed(Duration(seconds: 3), (){
      return 'result 2';
    })
  ]).listen((event) {
    print('listen: $event');
  }, onError: (e){
    print('err: $e');
  }, onDone: (){
    print('finish!');
  });

// 打印
listen: result 1
err: Assertion failed: "sorry!"
listen: result 2
finish!

四、async、await/await-for

  • async/await只是一個(gè)語(yǔ)法糖,本質(zhì)還是Future對(duì)象。
    Dart語(yǔ)言中 async/await 和JavaScript中一樣,都只是一個(gè)語(yǔ)法糖,編譯器或解釋器最終都會(huì)將其轉(zhuǎn)化為一個(gè) Future(Promise) 對(duì)象的調(diào)用鏈。

  • async函數(shù)中,在await語(yǔ)句之前,是同步執(zhí)行。
    An async function runs synchronously until the first await keyword.

  • await 會(huì)阻塞當(dāng)前函數(shù),知道完成。

// 倒計(jì)時(shí)
void countSeconds(int s) {
  for (var i = 1; i <= s; i++) {
    Future.delayed(Duration(seconds: i), () => print(i));
  }
}

// 延遲例子
Future<void> printOrderMessage() async {
  print('Awaiting user order...');
  var order = await fetchUserOrder();
  print('Your order is: $order');
}

Future<String> fetchUserOrder() {
  return Future.delayed(const Duration(seconds: 4), () => 'Large Latte');
}

Future<void> main() async {
  countSeconds(4);
  await printOrderMessage();
}

// 輸出
Awaiting user order...
1
2
3
4
Your order is: Large Latte

1、await --> Future

  • await必須在async聲明的函數(shù)中調(diào)用。
String lookUpVersion() {
  return '0.0.1';
}

Future<void> checkVersion() async {
  var version = await lookUpVersion();
  print(version);
}
  • await 語(yǔ)句一般會(huì)返回一個(gè) Future對(duì)象,如果不是則會(huì)自動(dòng)包裹為一個(gè)Future對(duì)象。

2、await for --> Stream

  • 格式:變量expression 必須為Stream類(lèi)型
await for (varOrType identifier in expression) {
  // Executes each time the stream emits a value.
}
  • await for必須在async聲明的函數(shù)中調(diào)用。
Future<void> main() async {
  await for (final request in requestServer) {
    handleRequest(request);
  }
}
  • Execution proceeds as follows:
    Wait until the stream emits a value.
    Execute the body of the for loop, with the variable set to that emitted value.
    Repeat 1 and 2 until the stream is closed.

  • 可以使用break/return跳出循環(huán)。
    To stop listening to the stream, you can use a break or return statement, which breaks out of the for loop and unsubscribes from the stream.

3、捕獲async的異常。

try {
  print('Awaiting ...');
} catch (err) {
  print('Caught error: $err');
}
參考

in the library tour

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容