还没搞懂async和await?看完这篇还不懂的话你来静步我
Posted 编程的平行世界
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了还没搞懂async和await?看完这篇还不懂的话你来静步我相关的知识,希望对你有一定的参考价值。
前言:最近在帮一些朋友改Bug的时候,总是会有一些奇怪的问题(说实话给我整懵了),仔细排查后发现是语法写错了,说多了都是泪,当初入门Flutter时,发现Dart语法与Java很相似,就没有仔细学习Dart的语法,现在这基础不扎实的弊端就体现出来了😖
(对于使用Js和Dart的程序员都建议仔细阅读这篇文章,因为都是单线程的语言)
什么是异步,理解这个很重要!!
简单解释:
同步一般指两个任务之间执行次序有先后之分
异步一般指同时做多件事(我就问你下面这张图形象吗👍)
常见的一些异步操作:
1)网络请求时
2)写入数据库时
3)从文件读取数据时
Dart中的异步
这里给了我们两个实现异步逻辑的方法
官方:
这里我们详解Future
使用Future
一般常用的Future构造函数:
所以代码都可以在这里运行:https://dartpad.dev/
new Future(()
// 这里写业务代码
);
当然还有分治的任务,需要将一个大人物拆成很多小任务一步一步执行,需要使用Future.then函数来拆解任务
new Future(() => 自定义的函数) // 异步任务的函数
.then((a) => "返回:$a") // 任务执行完后的子任务
.then((a) => a.length) // 其中a为上个任务执行完后的返回的结果
.then((a) => printLength(a))
.whenComplete(() => whenTaskCompelete); // 当所有任务完成后的回调函数
当任务需要延迟执行时,可以使用new Future.delay来将任务延迟执行
Future.delayed(const Duration(seconds: 2), () => print(''));
举一个简单的例子:
void main()
print('开始运行');
getUserMessage();
Future<void> getUserMessage()
//假设我们在请求一些数据
return Future.delayed(const Duration(seconds: 2), () => print('获取到网络的信息'));
结果应该是:
开始运行
//过两秒后
获取到网络的信息
使用 async-await
这是实现异步逻辑的一种语法
记住两个准则:
记住以下两个基本准则:
- 要定义异步函数,请在函数体之前添加async:
- await关键字仅在async函数中起作用。
在同步函数的基础上给一个简单的例子:
void main()
print('开始运行');
getUserMessage();
Future<void> getUserMessage() async
print(await postUserInput());
//假设我们在请求一些数据
return Future.delayed(const Duration(seconds: 2), () => print('获取到网络的信息'));
//假设我们在发送一些数据,当然正常情况下,发送数据也是异步的
Future<String> postUserInput() =>
Future.delayed(
const Duration(seconds: 2),
() => '我发送了数据',
);
返回结果是正确的:
开始运行
我发送了数据
获取到网络的信息
但是如果没有使用await
print(postUserInput());
这个时候就会打印出:
开始运行
Instance of '_Future<String>'
获取到网络的信息
为什么呢?
解析:
- postUserInput() 是一个异步函数,它在延迟后打印“我发送了数据”
- 正确的情况应该是等待postUserInput()运行完成再请求数据,但是这里没有使用await,就是没有得到返回的字符串
- 所以这里无法正确的描述postUserInput(),只能返回它是一个Future的实例
如果使用把这个函数赋值给变量是会报错的
String data = postUserInput();
解析与上面相同
顺序处理
你可以使用多个 await
表达式来确保各个语句在执行下一个语句之前完成:
// 使用关键字 async 和 await 顺序处理异步函数逻辑
main() async
await A();
await B();
test(await C());
async-await总结:
- 要想 return await … ,那么函数首先是 async 的
- 使用 async 标注的函数或者是异步的函数,必须要用 await 接收返回值,如:var data = await postUserInput();
使用then:
then回调:(在完成请求功能后不想停留直接运行下一个代码块)
Future<R> then <R>(
FutureOr<R> onValue(
T value
),
Function onError
)
举一个简单的例子:
void main()
print('开始运行');
Future.delayed(Duration(seconds: 1), ()
print('请求数据');
).then((a)
print('获取到的数据$a');
);
输出:
开始运行
请求数据
获取到的数据null
then与await的区别总结:
then的回调类似于观察者模式,then主要目的是在Future完成的时候再来处理value从而避免阻塞,而await会暂停所在的async函数的执行,对于堆栈来说这个不同点十分关键!!
处理异常错误
处理async中的错误需要使用try
Future<void> printDailyNewsDigest() async
try
var newsDigest = await gatherNewsReports();
print(newsDigest);
catch (e)
// 处理代码执行错误...
使用catchError与whenComplete
Future还有两个比较常用的api,catchError、whenComplete。 catchError用于捕捉错误,whenComplete在什么情况都会调用,
一般来说,如果需要监听“结束”这个状态,那么用whenComplete,需要监听“成功”这个状态,用then,需要监听“失败”这个状态,用catchError,就是这么滴简单~
catchError方法和then方法是同一级别的,catchError是最后的保障,catchError与then方法的onError参数不同的是,catchError可以处理之前所有处理过程中产生的error,而onError只能够处理调用then的Future对象的异常
Future.then((value)=>getUserMessage(value), onError: (e)).then().catchError();
在这里,onError只能够捕获Future的异常,但是catchError可以捕获Future和getUserMessage中产生的异常。
文字不多,但是都是用心总结的,所以,兄弟们给个赞呗,如果哪里说的不完整或者错了,在评论区告诉我,感谢~
以上是关于还没搞懂async和await?看完这篇还不懂的话你来静步我的主要内容,如果未能解决你的问题,请参考以下文章