async/await是Future/then的语法糖,官方为了解决Future/then的死亡嵌套,出的语法糖。下面写一下他们之间的转换关系

下面是一个async/await的语法糖写法

  1. test() async {
  2. print('test');
  3. await Future(() async {
  4. print('f1');
  5. await Future(() => print('f2'));
  6. print('f1-2');
  7. });
  8. print('test-2');
  9. }

下面是转化为Future/then原始写法

  1. test2() {
  2. print('test');
  3. return Future(() {
  4. print('f1');
  5. return Future(() => print('f2')).then((value) => print('f1-2'));
  6. }).then((value) => print('test-2'));
  7. }

下面说一下具体的转化过程

首先说明几个点:

  1. async声明的函数为异步函数,返回值是一个Future对象
  2. await关键字表示异步等待,await下方的代码在异步任务结束后才会执行

    下面我们先分析一下async/await的执行顺序

    1,test方法被调用后,首先打印test,因为他是同步方法。
    image.png
    2,然后遇到第一个await关键字,这时候await关键字将整个方法体分成2部分,await之后的代码块2需要等待代码块1执行完后才可以执行。所以会打印f1。
    image.png
    3,同理,f2和f1-2会以此打印。
    image.png
    4,最后打印test-2
    image.png
    5,所以整个的打印顺序为
    image.png

    然后我们在看一下async/await语法糖是如何转化为Future/then的写法的

  • 去掉async关键字;
  • await关键字声明的Future,将作为test的返回值;
  • await关键字下方的代码块,将作为Future的then函数中的函数体。

image.png
image.png
2,同理,继续转化内部的async/await语法糖

  • 去掉async关键字;
  • await关键字声明的Future,将作为test的返回值;
  • await关键字下方的代码块,将作为Future的then函数中的函数体。

image.png

最后看一下转换后的代码执行顺序

image.png
打印顺序如下
image.png
可以看出,转化后的代码和转化前执行顺序是完全一致的。

总结

熟悉async/await语法糖和Future/then的转化可以让我们对于事件循环机制更加清楚,转化步骤只需要3步口诀:
1隐:隐藏async关键字
2返:await关键字声明的Future变为返回值
3替换:await关键字一下的所有代码块都作为Future的then函数体