您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

「google教程」async/await的使用和原理

时间:2019-11-20 10:33:33  来源:  作者:

文章授权首发于code4flutter,如需转载请注明来源 https://code4flutter.com/async-await-usage/

本文是flutter油管教程第3篇,介绍async和await的使用和原理

引言

很多语言使用async和await作为语法,将函数变成async,然后在代码的某个位置,它会进行等待,直到任务处理完成返回。在flutter中也是这样的基本功能,但是需要特别指出的是这种语法糖只是feature和stream的封装,可以让你更清晰的更易读的代码。

对比

「google教程」async/await的使用和原理

 

这里是一个处理数据处理的例子,网络请求和文件IO操作是异步操作

我们想让他们放在一起工作,首先通过网络请求创建一个id,根据这个id进行网络通信,然后用结果创建一个processdata的对象,使用dart的feature的api,然后将回调链接在一起。这样用前一个的回调作为下一个回调的参数输入,以此类推。但是之前的方式并不具有很好的可读性,需要层层嵌套,但是用feature结合async和wait不一样。

ProcessedData createData() async{
 final id = _loadFromDisk();
 final data = _fetchNetworkData(id);
 return ProcessedData(data);
}复制代码

首先,添加async关键字,只是告诉编译器,“嘿,我打算在这里使用await关键字”

接下来我们来添加await关键字,在每个feature之前,标志需要等待的函数,

最后,在返回值添加feature关键字,有人觉得很奇怪,为什么只是普通的返回处理数据结果的函数需要feature修饰呢,这是因为在processData之前有两次异步操作用到了await。这意味着他开始执行,然后停止,等待磁盘事件,然后继续,然后停下来等待网络事件。只有在那之后才能提供一个值。代码如下:

ProcessedData createData() async{
 final id = await _loadFromDisk();
 final data = await _fetchNetworkData(id);
 return ProcessedData(data);
}复制代码

asyc/await 工作原理

所以当createData开始运行并触发第一个await时,他才会返回一个feature,到调用函数,他说,“嘿,我需要等待一下东西”,这是一个空盒子,你需要等待一会儿,当我在网络中等待的磁盘数据到达时,我将调用return语句并为你提供一些数据,把它放入futurebuilder,或其他东西中,这就是他的工作原理。用代码翻译如下:

Future<ProcessedData> createData(){
 return _loadFromDisk().then((id){
 return _fetchNetworkData(id);
}).then((data){
 return ProcessData(data);
})
}复制代码

用feature api的好处就是你可以清楚的看到代码是如何将事件进行拆分的。首先函数开始执行,调用loadfromdisk,等待来来自磁盘的数据触发事件循环,然后第二个回调被调用,请求网络,等待来自网络的数据到达事件循环,然后处理数据。此时调用return,此时该值完成了。

「google教程」async/await的使用和原理

事件循环

现在我们使用async/await版本实现。通过await表达式作为等待。由此可以得到以下代码。

async/await正确姿势

Future<ProcessedData>createData() async{
 final id = await _loadFromDisk();
 final data = await _fetchNetworkData(id);
 return ProcessedData(data);
}复制代码

createData开始执行,并触发第一个等待,此时它将自己的future返回给函数,并调用loadFromDisk,然后像之前一样,等待来自磁盘文件I/O事件,这样就完成了由loadFromDisk返回的future,这意味着createData结束了等待,并可以继续执行其余的代码了。再次等待,请求网络数据等待返回,最终网络数据到达事件循环,这就完成了由fetchNetworkData返回的future。createData就可以再次继续运行了,他创建并返回了一个ProcessedData的实例。他完成了createData在开头处传给调用者的那个future。

由此可以看到,相同的事件循环控制着代码的运行,并涉及到相同的future,唯一变化的是,有了async/await,函数代码变少了,看起来更像是同步的代码。

async/await如何处理错误

普通的写法,处理错误如下,

「google教程」async/await的使用和原理

 

使用catcherror来处理错误,完成后悔在最后执行回调,无论是否有错误发生。

在aync/await的方式中不用任何回调,而是用try catch

「google教程」async/await的使用和原理

 

可以使用try catch捕获特定类型的异常,finally将在最后执行其代码块。

如何处理循环

如我们普通的循环写法。用for来循环迭代值

int getTotal(List<int> numbers){
 int total = 0;
 for(final value in numbers){
 total +=value;
 }
 return total;
}复制代码

但是如果我们这个函数读取的是一个由数字组成的stream,该怎么办,按照他们的异步到达的次序来进行求和,然后返回求和值,和aync awaite的方式一样,不用改变代码基本结构。

首先,先将函数标志位async

然后,将返回值更改为future

然后,在前面添加关键字await。完成。代码如下:

Future<int> getTotal(List<int> numbers) async{
 int total = 0;
 await for(final value in numbers){
 total +=value;
 }
 return total;
}复制代码

和future一样,await关键字将我的函数,拆分为等待事件之前执行和之后执行,两部分代码,首先,他开始执行,一直到await,然后将其future返回给调用函数,并等待一段数据到达。当数据到达时,循环执行一次来处理那条数据,然后停下来,并等待下一条数据,也许此时应用程序会运行并执行其他一些操作,如垃圾回收,最终另一条数据到来了,然后循环再次执行,这种情况一直循环,直到stream结束并关闭,此时该函数退出循环,并执行其return语句。这样就完成了getTotal在最初返回给它的调用者的feture。

有一点要注意的是,当你使用stream时,保证要处理的streams最终会完成。如果遇到如html查找一个按钮点击,这个按钮一直没出来就无法完成,则函数会一直等待的状态。

参考

Get started with Flutter → flutter.dev Try a Flutter codelab → goo.gl/d3fHPo Join the conversation → goo.gl/68oUnb



Tags:async/await   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
1、前言async函数,也就是我们常说的async/await,是在ES2017(ES8)引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法。async和await关键字让我们可以用一种更简...【详细内容】
2021-09-17  Tags: async/await  点击:(61)  评论:(0)  加入收藏
一般在开发中,查询网络 API 操作时往往是比较耗时的,这意味着可能需要一段时间的等待才能获得响应。因此,为了避免程序在请求时无响应的情况,异步编程就成为了开发人员的一项基...【详细内容】
2021-03-31  Tags: async/await  点击:(260)  评论:(0)  加入收藏
大家好,前几篇文章我们一起学习了「JavaScript基础」Promise使用指南, 明白了ES6增加的新特性&mdash;&mdash;Promise让我们能够更加优雅的书写回调函数,清楚了Promise有哪些...【详细内容】
2021-03-30  Tags: async/await  点击:(267)  评论:(0)  加入收藏
微信小程序中有大量接口是异步调用,比如 wx.login() 、 wx.request() 、 wx.getUserInfo() 等,都是使用一个对象作为参数,并定义了 success() 、 fail() 和 complete() 作为异...【详细内容】
2020-03-11  Tags: async/await  点击:(93)  评论:(0)  加入收藏
很多语言使用async和await作为语法,将函数变成async,然后在代码的某个位置,它会进行等待,直到任务处理完成返回。在flutter中也是这样的基本功能,但是需要特别指出的是这种语法糖只是feature和stream的封装,可以让你更清晰...【详细内容】
2019-11-20  Tags: async/await  点击:(93)  评论:(0)  加入收藏
▌简易百科推荐
本文分为三个等级自顶向下地分析了glibc中内存分配与回收的过程。本文不过度关注细节,因此只是分别从arena层次、bin层次、chunk层次进行图解,而不涉及有关指针的具体操作。前...【详细内容】
2021-12-28  linux技术栈    Tags:glibc   点击:(3)  评论:(0)  加入收藏
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(2)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(10)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(20)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(25)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(25)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条