美文网首页
2.4、Dart语言基础:异步

2.4、Dart语言基础:异步

作者: 双鱼子曰1987 | 来源:发表于2021-12-16 08:40 被阅读0次

    学习笔记,旨在于快速入门和学习Dart,其中可能会有理解错误,请指出,一起学习。

    系列文章

    2.1、Dart语言基础:变量、运算符
    2.2、Dart语言基础:函数与闭包
    2.3、Dart语言基础:面向对象
    2.4、Dart语言基础:异步
    2.5、Dart语言基础:库与包
    ...

    一、概述

    1、异步使用常见

    • 网络获取数据。
    • 读写数据库。
    • 读写文件。

    2、Dart语言中,异步相关的两个对象Future or Stream

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

    • Future表示的是:单个计算结果的异步封装。
      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表示的是:多个序列化事件的异步封装。其很像是一个异步的迭代器。
      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 语法糖。
    • 使用Future or Stream 相关APIs。

    4、导入头文件import 'dart:async';


    二、Future

    • Future对象代表两个状态:Uncompleted未完成、Completed完成(成功或者失败)。
      A future represents the result of an asynchronous operation, and can have two states: uncompleted or completed.

    1、常用接口

    .then 状态完成后回调
    .delayed 延迟多少秒后,执行回调
    .whenComplete 无论成功和失败都会执行
    .catchError 发生错误,必须在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 阻塞函数执行,等待wait函数里面的任务都完成,才会往下。
      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、多个Future对象

    • 链式串联多个异步方法
      Future result = costlyQuery(url);
      result.then((value) => expensiveWork(value))
      .then((_) => lengthyComputation())
      .then((_) => print('Done!'))
      .catchError((exception) {
        /* Handle exception... */
      }); 
    
    // 等价于
    try {
      final value = await costlyQuery(url);
      await expensiveWork(value);
      await lengthyComputation();
      print('Done!');
    } catch (e) {
      /* Handle exception... */
    }
    
    • Future.wait:等待所有Future执行完,才继续执行。
    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

    • 主要用来:异步处理 序列化的数据。例如,文件流、点击事件流。

    1、在循环中使用异步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);
        }
      });
    }
    
    // 等价于
    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的所有结果时候,才使用await for

    2、常用接口

    监听流的数据或事件

    • .listen 所有值
    submitButton.onClick.listen((e) {
      // When the button is clicked, it runs this code.
      submitData();
    });
    
    • 单个数据
    first()
    last()
    single()
    // 单个数据前的拦截测试
    firstWhere()
    lastWhere()
    singleWhere()
    
    • 一组流数据
    skip()
    skipWhile()
    take()
    takeWhile()
    where()
    

    流数据转换(Transforming stream data)

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

    完成状态

    • 成功 .onDone
    • 错误 . onError

    3、Stream 和 Future 的区别点

    • Stream和Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。

    • Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。

      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只是一个语法糖,本质还是Future对象。
      Dart语言中 async/await 和JavaScript中一样,都只是一个语法糖,编译器或解释器最终都会将其转化为一个 Future(Promise) 对象的调用链。

    • async函数中,在await语句之前,是同步执行。
      An async function runs synchronously until the first await keyword.

    • await 会阻塞当前函数,知道完成。

    // 倒计时
    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声明的函数中调用。
    String lookUpVersion() {
      return '0.0.1';
    }
    
    Future<void> checkVersion() async {
      var version = await lookUpVersion();
      print(version);
    }
    
    • await 语句一般会返回一个 Future对象,如果不是则会自动包裹为一个Future对象。

    2、await for --> Stream

    • 格式:变量expression 必须为Stream类型
    await for (varOrType identifier in expression) {
      // Executes each time the stream emits a value.
    }
    
    • await for必须在async声明的函数中调用。
    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跳出循环。
      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

    相关文章

      网友评论

          本文标题:2.4、Dart语言基础:异步

          本文链接:https://www.haomeiwen.com/subject/tmpefrtx.html