Dart 异步模型

Dart汇总请点击这里

Future

Future模型是将异步请求和代理模式结合的产物。
Future类是对未来结果的一个代理,它返回的并不是被调用的任务的返回值。

//我的任务
void  myTask(){
    print("this is my task");
}

void  main() {
    Future fut = new  Future(myTask);//根据我的任务创建Future对象
}

如上代码,Future类实例fut并不是函数myTask的返回值,它只是代理了myTask函数,封装了该任务的执行状态。换种理解方式就是,Future就是一个受你委托的委托人,你将未来要执行的任务交给他,你告知他任务类型是耗时任务,还是非耗时任务,然后分类放到事件循环中去,当任务完成后,它会第一时间执行回调方法告知你任务完成,或者会等到你委托给他的所有任务都完成了立马告知你。

创建Future

Future的几种创建方法

Future()
Future.microtask()
Future.sync()
Future.value()
Future.delayed()
Future.error()

其中sync是同步方法,任务会被立即执行

import  'dart:async';

void  main() {
    print("main start");

new  Future.sync((){
    print("sync task");
});

new  Future((){
    print("async task");
});

    print("main stop");
}

运行结果:

main start
sync task
main stop
async task
注册回调

使用then注册回调

当Future中的任务完成后,我们往往需要一个回调,这个回调立即执行,不会被添加到事件队列。

import 'dart:async';

void main() {
  print("main start");

  Future fut =new Future.value(18);
  // 使用then注册回调
  fut.then((res){
    print(res);
  });

 // 链式调用,可以跟多个then,注册多个回调
  new Future((){
    print("async task");
  }).then((res){
    print("async task complete");
  }).then((res){
    print("async task after");
  });

  print("main stop");
}

运行结果:

main start
main stop
18
async task
async task complete
async task after

除了then方法,还可以使用catchError来处理异常,如下

  new Future((){
    print("async task");
  }).then((res){
    print("async task complete");
  }).catchError((e){
    print(e);
  });

还可以使用静态方法wait 等待多个任务全部完成后回调。

import 'dart:async';

void main() {
  print("main start");

  Future task1 = new Future((){
    print("task 1");
    return 1;
  });

  Future task2 = new Future((){
    print("task 2");
    return 2;
  });
    
  Future task3 = new Future((){
    print("task 3");
    return 3;
  });

  Future fut = Future.wait([task1, task2, task3]);
  fut.then((responses){
    print(responses);
  });

  print("main stop");
}

运行结果:

main start
main stop
task 1
task 2
task 3
[1, 2, 3]

如上,wait返回一个新的Future,当添加的所有Future完成时,在新的Future注册的回调将被执行。

Future的特点

  • Future中的then并没有创建新的Event丢到Event Queue中,而只是一个普通的Function Call,在FutureTask执行完后,立即开始执行

  • Future如果在then()调用之前Future就已经执行完毕了,那么会有一个任务被加入到microtask队列中。这个任务执行的就是被传入then的方法

  • Future只是创建了一个Event,将Event插入到了Event Queue的队尾

  • Future.value创建Task到microtask Queue中执行then传入的函数

  • Future.sync执行了它传入的函数之后,也会立即创建Task丢到microtask Queue中执行

  • Future.wait等待多个任务全部完成后回调。wait返回一个新的Future,当添加的所有Future完成时,在新的Future注册的回调将被执行。

  • Future.delayed在延时一定时间后向队列插入一个任务
    虽然可以预测任务执行的顺序,但是我们无法预测事件循环什么时候会从队列中提取任务。Dart事件处理系统基于单线程循环,而不是基于时基(tick,系统的相对时间单位)或者其他的时间度量。例如,当你创建一个延时1s的任务,1s后向事件队列添加一个任务,但在该任务之前的任务结束前,事件循环是不会处理这个任务的,也就是说该任务执行可能是大于1s的。

async 和 await

在Dart1.9中加入了async和await关键字,有了这两个关键字,我们可以更简洁的编写异步代码,而不需要调用Future相关的API。他们允许你像写同步代码一样写异步代码和不需要使用Future接口。

将 async 关键字作为方法声明的后缀时,具有如下意义

被修饰的方法会将一个 Future 对象作为返回值
该方法会同步执行其中的方法的代码直到第一个 await 关键字,然后它暂停该方法其他部分的执行;
一旦由 await 关键字引用的 Future 任务执行完成,await的下一行代码将立即执行。

// 导入io库,调用sleep函数
import 'dart:io';

// 模拟耗时操作,调用sleep函数睡眠2秒
doTask() async{
  await sleep(const Duration(seconds:2));
  return "Ok";
}

// 定义一个函数用于包装
test() async {
  var r = await doTask();
  print(r);
}

void main(){
  print("main start");
  test();
  print("main end");
}

运行结果:

main start
main end
Ok

注意:需要注意,async 不是并行执行,它是遵循Dart 事件循环规则来执行的,它仅仅是一个语法糖,简化Future API的使用。

Future 原理

Dart 是事件驱动的体系结构,该结构基于具有单个事件循环两个队列的单线程执行模型。 Dart虽然提供调用堆栈。 但是它使用事件在生产者和消费者之间传输上下文。 事件循环由单个线程支持,因此根本不需要同步和锁定。
详细请参阅我的另一篇文章: Dart 事件循环

使用 Future 控制任务调度

将任务添加到MicroTask队列立即执行或将任务添加到Event队列空闲执行
详细请参阅我的另一篇文章:Dart 任务调度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值