Flutter -- 9.异步编程

一.使用Future异步编程

  • Dart中使用Future完成异步操作

1.基本的异步代码示例

aboutFuture() {
  print('外部代码1');
  Future(() {
    print('执行任务A');
    // throw Exception('error');
    return '任务A';
  }).then((value) => print('$value完成'))
    .whenComplete(() => print('异步完成'))
    .timeout(Duration(seconds: 1))
    .catchError((e) {
      print(e);
    });
  print('外部代码2');
  // flutter: 外部代码1
  // flutter: 外部代码2
  // flutter: 执行任务A
  // flutter: 任务A完成
  // flutter: 异步完成
}
  • 任务代码块,执行的异步任务
  • throw Exception(''),抛出异常
  • return,返回数据,then代码块回调参数值value
  • then, 处理future返回值的代码块。then本质就是将里面的代码丢到微任务队列去执行,因此事件执行完会优先执行.then
  • whenComplete,当任务代码块及.then执行完成时回调
  • timeout,异步任务设置的超时时间
  • catchError,捕获异常的回调
    注意:一般将catchError写在链的最后面,catchError返回值为Future,其他方法返回Future,如果先写了catchError,后续如果抛异常程序就会报错,因此一般写在链的最后面

2.async和await

aboutAwaitAndAsync() async {
  print('外部代码1');
  await Future((){
    //耗时操作
    //1.后面的操作必须是异步的才能使用await修饰
    //2.当前这个函数也必须是async修饰的
    for (int i = 0 ; i < 10000000000; i ++) {}
    return '遍历完毕';
  }).then((value) => print(value));
  print('外部代码2');
  // flutter: 外部代码1
  // flutter: 遍历完毕
  // flutter: 外部代码2
}

3.多个异步任务

  • 多个任务按事件队列顺序执行
//1.初识Future,多个任务按事件队列顺序执行
testFuture() {
  print('外部代码1');
  Future(() {
    return '任务1';
  }).then((value) => print(value));
  Future(() {
    sleep(Duration(seconds: 2));
    return '任务2';
  }).then((value) => print(value));
  Future(() {
    return '任务3';
  }).then((value) => print(value));
  Future(() {
    return '任务4';
  }).then((value) => print(value));
  print('外部代码2');
  // flutter: 外部代码1
  // flutter: 外部代码2
  // flutter: 任务1
  // flutter: 任务2
  // flutter: 任务3
  // flutter: 任务4
}

4.多个任务执行完后,再执行某个任务

  • 使用wait
//2.wait,当所有任务执行完成后,会执行then
testFuture2() {
  Future.wait([Future(() {
    return '任务1';
  }), Future(() {
    return '任务2';
  }),Future(() {
    return '任务3';
  })]).then((value) => print(value[0] + value[1] + value[2]));
}

5.Future.value

  • 创建指定返回值的Future
futureValue() async {
  int a = await Future.value(1);
  print(a); //1
}

6.Future.delayed

  • 延迟执行一个异步任务
futureDeley() {
  print('外部代码1');
  Future.delayed(Duration(seconds: 2), () {
    print('开始任务');
  });
  print('外部代码2');
  // flutter: 外部代码1
  // flutter: 外部代码2
  // flutter: 开始任务
}

7.Future.error

  • 创建一个Future异常错误
futureError() {
  Future.error('Test Error').catchError((e)=>print(e)); //Test Error
}

8.Future.error与.then中的onError

  • Future.catchError,一般用于获取原始Future抛出的Error(包含Future代码块里抛出的异常),不能处理回调函数抛出的Error(比如then、catchError)
  • onError,只能处理当前Future的错误
futureError() {
  Future.error('Test Error').then((value) {
    throw '.then error';
  }).catchError((e) {
    print(e); //Test Error
    throw '.then error2';
  }).then(print, onError: (e)=>print(e));// .then error2
}

9.Flutter.timeout

  • 模拟超时
futureTimeout() {
  Future.delayed(Duration(seconds: 2)).timeout(Duration(seconds: 1)).catchError(print);
}

10.Future.foreach

  • 遍历List/Map,转化为[Future]
futureForeach() {
  Future.forEach({1,2,3}, (num) {
    return Future.delayed(Duration(seconds: num as int), () {
      print("第$num秒执行");
    });
  });
  // flutter: 第1秒执行
  // flutter: 第2秒执行
  // flutter: 第3秒执行
}

11.Future.any

  • 返回第一个执行完成的Future,无论结果是正确的还是异常
futureAny() {
  Future.any([1,2,3].map((e) => Future.delayed(Duration(seconds: e), ()=>e))).then(print).catchError(print); //1
}

12.Future.doWhile

  • 重复的执行某个动作,直到返回false/true
  • true - 执行循环,false - 退出循环
futureDoWhile() {
  Future.doWhile(() {
    int num = Random().nextInt(20);
    print(num);
    if (num == 5) {
      print('doWhile结束');
      return false;
    }else {
      return true;
    }
  });
}

13.Future.sync

  • 添加同步任务时,会阻塞当前线程,sync执行完成后,才能执行下一行代码
futureSync() {
  Future(()=>print('任务1'));
  Future.sync(()=>print('任务2'));
  Future(()=>print('任务3'));
  Future.microtask(() => print('任务4'));
  // flutter: 任务2
  // flutter: futureSync
  // flutter: 任务4
  // flutter: 任务1
  // flutter: 任务3
}
futureSync();
print('futureSync');
Future.microtask
  • 创建一个在microtask queue运行的Future,microtask queue优先级>event queue。因此位于micro queue上的Future会优先于其它Future。相当于添加了一个微任务

14.微任务(Micro Task)

  • 表示一个短时间内就会完成的异步任务,它的优先级最高
//3.初识微任务,微任务优先级高
testFuture3() {
  print('外部代码1');
  Future(()=>print('A')).then((value) => print('A结束'));
  Future(()=>print('B')).then((value) => print('B结束'));
  scheduleMicrotask(() {
    print('微任务A');
  });
  print('外部代码2');
  // flutter: 外部代码1
  // flutter: 外部代码2
  // flutter: 微任务A
  // flutter: A
  // flutter: A结束
  // flutter: B
  // flutter: B结束
}

15.关于微任务与事件任务优先级的一些练习

//7.微任务与事件任务执行顺序练习
testFuture7() {
  Future x1 = Future(()=>null);
  Future x = Future(()=>print('1'));
  Future(() {
    print('2');
    scheduleMicrotask(()=>print('13'));
    x1.then((value){
      print('6');
      scheduleMicrotask(()=>print('7'));
    }).then((value) => print('8'));
  });
  scheduleMicrotask(()=>print('3'));
  x.then((value) => print('4'));
  Future(() {
    print('9');
    Future(()=>print('10'));
  }).then((value) => print('11'));
  Future(()=>print('12'));
  print('5');
  //5、3、1、4、2、13、6、8、7、9、11、12、10
}

//6.微任务与事件任务执行顺序练习
testFuture6() {
  Future x1 = Future(()=>null);
  Future x = Future(()=>print('1'));
  Future(() {
    print('2');
    x1.then((value){
      print('6');
      scheduleMicrotask(()=>print('7'));
    }).then((value) => print('8'));
  });
  scheduleMicrotask(()=>print('3'));
  x.then((value) => print('4'));
  print('5');
  //53142687
}

//5.微任务与事件任务执行顺序练习
testFuture5() {
  Future x1 = Future(()=>null);
  Future x = Future(()=>print('1'));
  Future(()=>print('2'));
  scheduleMicrotask(()=>print('3'));
  x.then((value) => print('4'));
  print('5');
  x1.then((value){
    print('6');
    scheduleMicrotask(()=>print('7'));
  }).then((value) => print('8'));
  //53687142
}

//4.微任务与事件任务执行顺序练习
testFuture4() {
  Future x = Future(()=>print('1'));
  Future(()=>print('2'));
  scheduleMicrotask(()=>print('3'));
  x.then((value) => print('4'));
  print('5');
  //53142
}

二.Event Loop(事件循环)

  • 每一次事件循环中,Dart总是先去第一个microtask queue中查询是否有可执行的任务,如果没有,才会处理后续的event queue
  • 事件队列(event queue),包含所有的外来事件:I/Omouse eventsdrawing eventstimersisalate之间的信息传递
  • 微任务队列(microtask queue),表示一个短时间内就会完成的异步任务,它的优先级最高。只要队列中还有任务,就可以一直霸占着事件循环。microtask queue添加的任务主要是由 Dart内部产生
    注意:如果有太多的微任务,可能会霸占着事件循环,导致event queue中的触摸、绘制等外部事件造成阻塞卡顿

你可能感兴趣的:(Flutter -- 9.异步编程)