用Dart语言来写异步程序

Posted 郭霖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Dart语言来写异步程序相关的知识,希望对你有一定的参考价值。


/   今日科技快讯   /

软银集团希望出120-150亿美元售阿里巴巴的股份,这是软银集团为应对新冠肺炎疫情影响而采取的410亿美元融资计划的部分内容。目前软银集团资产负债表上有超过27万亿日元(2450亿美元)的资产,以及1.7万亿日元(150亿美元)的现金。而其中,最有价值的持股中就包括阿里巴巴。

/   作者简介   /

本篇文章来自android_zhu_jiang的投稿,详细地分析了Dart语言中的异步,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。

Android_zhu_jiang的博客地址:
https://blog.csdn.net/haojiagou

/   正文   /

废话不多说,开始进入今天的主题吧!

async 和 await


开始说这两个关键字之前我觉得有必要提一下:在Dart中没有子线程一说,所有代码都是在一条主线上运行的,所以需要用异步来实现一些耗时操作。(如果非要开启多线程需要使用隔离,这里不做叙述)

来说一下这两个关键字吧,async用来修饰方法,需要写在方法括号的后面,await写在方法里面,这里要注意:await关键字必须在async函数内部使用,不然会报错。await表达式可以使用多次。这里其实很好理解:都不是异步方法了你还等待啥啊?下面看一个简单的样例吧:

  
    
    
  
void main() {
  getName1();
  getName2();
  getName3();
}

getName1() async {
  await getStr1();
  await getStr2();
  print('getName1');
}

getStr1() {
  print('getStr1');
}

getStr2() {
  print('getStr2');
}

getName2() {
  print('getName2');
}

getName3() {
  print('getName3');
}

上面这段代码并不长,大家可以猜一下打印出来的值。

咱们来一步一步分析吧,后面再贴出来答案,看看大家猜的对不对。

首先执行getName1(),执行的时候发现这个方法是async的方法,继续执行,执行到方法中第一行的时候,发现调用了一个getStr1()方法,而且这个方法使用了await来修饰,表示需要等待执行

重点来了:当遇到await的时候会执行完这一行,打印出了getStr1,之后立即返回一个Future(void)对象(上面的代码中省略了这个,写代码时推荐加上,方便代码阅读理解),然后将这个方法中剩余的代码放入了事件队列,接着往下执行getName2()和getName3(),分别打印出了getName2和getName3

刚才也说过,在Dart中只有一个main线程一桶到底,还有一个事件队列,现在main线程中都已经执行完毕,但是事件队列中还有东西,继续执行getStr2(),执行的时候发现还是await,再进行等待,等待执行完成后打印getStr2,最后再打印getName1。

下面是打印出的结果:

  
    
    
  
getStr1
getName2
getName3
getStr2
getName1

和大家猜的一样吗?为什么会这样打印上面已经进行了分析。下面咱们看一下其他的几个关键字。

then,catchError,whenComplete


上面分析中说过,async方法中遇到await时即会返回一个Future对象,从字面上也能知道这个一个未来的值,那么肯定需要等待完成之后才能获取到里面的值。then关键字的意思就是获取等待执行完毕之后返回的值,光说感觉说不明白,还是来看一段代码吧:

  
    
    
  
void main() {
  new Future(() => futureTask())//异步任务的函数
      .then((i) => "result:$i")//任务执行完后的子任务
      .then((m) => print(m)); //其中m为上个任务执行完后的返回的结果
}

futureTask() {
  return 10;
}

上面这段代码中只有一个打印,下面是打印出的值:

  
    
    
  
result:10

为什么不只显示10呢?因为第二次then的时候参数m是第一次then返回的值,而不是futureTask()返回的10这里应该不难理解。

在then之后还可以抛异常,下面来抛一个异常来看看:

  
    
    
  
new Future(() => futureTask())//异步任务的函数
      .then((i) => "result:$i")//任务执行完后的子任务
      .then((m) => print(m)) //其中m为上个任务执行完后的返回的结果
      .then((_) => Future.error("出错了"));

从上面代码中可以知道抛异常的方法Future.error(“出错了”),来看一下执行情况:

  
    
    
  
result:10
Unhandled exception:
出错了
#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:1114:29)
#1      _microtaskLoop (dart:async/schedule_microtask.dart:43:21)
#2      _startMicrotaskLoop (dart:async/schedule_microtask.dart:52:5)
#3      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:393:30)
#4      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:418:5)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)

既然可以抛异常了,当然也可以catch异常,直接使用catchError关键字来捕获一下:

  
    
    
  
new Future(() => futureTask())//异步任务的函数
      .then((i) => "result:$i")//任务执行完后的子任务
      .then((m) => print(m)) //其中m为上个任务执行完后的返回的结果
      .then((_) => Future.error("出错了"))
      .catchError(print);

写法很简单,直接参照上面代码写即可,下面是运行结果:

  
    
    
  
result:10
出错了

以上是关于用Dart语言来写异步程序的主要内容,如果未能解决你的问题,请参考以下文章

用 Dart 来写 Objective-C 代码

Dart异步编程--Future

Dart异步编程之Future

Dart入门语言特性库异步编程

#yyds干货盘点#dart系列之:dart中的异步编程

持续发烧,试试Dart语言的异步操作,效率提升500%