Dart中的异步

news/2024/5/6 12:18:09/文章来源:https://blog.csdn.net/github_36850997/article/details/130028719

一 事件循环

flutter 就是运行在一个root isolate 中

程序只要运行起来,就有一个事件循环一直在运行 ,直至程序退出。

EventLoop 先从mrcro 对列中取任务,取完任务再去 event 队列中取任务。队列任务是FIFO。

二 认识Future

abstract class Future<T>

Future 是Dart 中提供的一个抽象类,泛型类,它用于封装一段在将来会被执行的代码逻辑。

Future就是异步中非常重要的角色。Future表示异步返回的结果,当执行一个异步延迟的计算时候,首先会返回一个Future结果,后续代码可以继续执行不会阻塞主isolate,当Future中的计算结果到达时,如果注册了 then 函数回调,对于返回成功的回调就会拿到最终计算的值,对于返回失败的回调就会拿到一个异常信息

1  基本使用

Flutter提供了下面三个方法,让我们来注册回调,来监听处理Future的结果。

 

//处理完成时候的回调,一般都是成功回调
Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
//处理失败的回调,比如throw一个error就会走到这里
Future<T> catchError(Function onError, {bool test(Object error)});
//Future.whenComplete总是在Future完成后调用,不管Future的结果是正确的还是错误的。
Future<T> whenComplete(FutureOr action());

 代码示例:

import 'dart:io';main(List<String> args) {// 阻塞主线程的调用// blockMainThread();// 异步调用asyncMethod();
}/*****----- 异步的调用方式 ---***/
void asyncMethod() {/*** main startmain endhello world* */print("main start");var future = getAsyncNetworkData();future.then((String value) {// 只有拿到结果 才会执行这里面的代码print(value);}).catchError((error) {// 打印结果 Exception: 我是错误信息print(error);}).whenComplete(() {// 代码走这,不管成功或者失败都会走这里print("代码执行完毕");});print("main end");
}Future<String> getAsyncNetworkData() {return Future<String>(() {sleep(Duration(seconds: 3));// return "hello world";// 抛出异常throw Exception("我是错误信息");});
}/*****----- 阻塞主线程的调用方式 ---***/
void blockMainThread() {/*** main startthis is hello worldmain end* */print("main start");var res = getNetworkData();print(res);print("main end");
}// 模拟网络请求
String getNetworkData() {// 阻塞2秒sleep(Duration(seconds: 2));return "this is hello world";
}

2 链式调用

  链式调用优势在于可以明确代码执行前后依赖关系以及实现异常的捕获

import 'dart:io';main(List<String> args) {print("main start");/*** main startmain end第一次网络请求的结果第二次网路请求的结果第三次网路请求的结果* * */// 这种方式可以解决回调地狱的问题 多个网络请求依赖也不用进行嵌套调用 直接链式调用即可Future(() {// 这是第一次网络请求sleep(Duration(seconds: 2));return "第一次网络请求的结果";}).then((res) {print(res);sleep(Duration(seconds: 2));// 这是第二次网络请求return "第二次网路请求的结果";}).then((res) {print(res);sleep(Duration(seconds: 2));return "第三次网路请求的结果";}).then((value) => print(value)).catchError((error) {print(error);});print("main end");
}

三 await 和 async

要定义异步函数,请在函数主体之前添加async关键字,他俩是配对出现的

他们是dart 语言中的关键字,最为重要的使用就是

可以让我们用同步的代码格式去实现异步的调用过程。
 

大部分Future使用的场景都可以使用async-await来替代,也建议使用async-await。

下面有这样一个需求 :比如说用户登录完成之后,拿到用户的token 去请求数据,就是请求之间的依赖

用 await async 方式实现 和 Future 实现比较

import 'dart:io';main(List<String> args) {print("main start");// getData();futureMethodData();print("main end");
}// future 的实现方式
futureMethodData() {Future(() {// 这是第一次网络请求sleep(Duration(seconds: 2));return "这是第一次网络请求结果";}).then((value) {print(value);sleep(Duration(seconds: 2));return value + "这是第二次网络请求结果";}).then((value) {print(value);sleep(Duration(seconds: 2));return value + "这是第三次网络请求结果";}).then((value) {print(value);});
}// async-await 的实现方式
getData() async {// 模拟三次网络请求/*** * main startmain endargs1helloworldargs1helloworldhelloworldargs1helloworldhelloworldhelloworld*/var res1 = await getNetworkData("args1");print(res1);var res2 = await getNetworkData(res1);print(res2);var res3 = await getNetworkData(res2);print(res3);
}getNetworkData(String args) {return Future(() {sleep(Duration(seconds: 2));return args + "helloworld";});
}

四 isolate

isolate  可以理解为dart 中的多线程,现在设备基本都是多核CPU,可以使用isolate 充分利用硬件资源。

isolate 之间是独立的,资源不共享的。每一个isaolate 都有自己的事件循环以及队列。

1 使用

import 'dart:io';
import 'dart:isolate';main(List<String> args) async {print("main start");// 1ReceivePort receivePort = ReceivePort();// 2  spawn 返回的是future 所以要异步操作Isolate isolate =await Isolate.spawn<SendPort>(calculate, receivePort.sendPort);// 可以给创建的isolate 中发送消息receivePort.sendPort.send("这是从main isolate 发送的消息");//3 监听创建的isolate的回调信息receivePort.listen((message) {print(message);// 收到结果 关闭 killreceivePort.close();isolate.kill();});print("main end");
}calculate(SendPort port) {// 模拟耗时操作sleep(Duration(seconds: 2));// 回调信息port.send("这是从创建的isolate 发送的信息");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_283882.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[JavaEE]----Spring03

文章目录Spring_day031&#xff0c;AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念2&#xff0c;AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知…

C++内存管理(new和delete)

目录 1. new/delete操作内置类型 2. new和delete操作自定义类型 3. operator new与operator delete函数 4 .new和delete的实现原理 1 .内置类型 2 .自定义类型 new的原理 delete的原理 new T[N]的原理 delete[]的原理 5. 定位new表达式(placement-new) 6. malloc/f…

使用Process Explorer和Clumsy定位软件高CPU占用问题

目录 1、问题描述 2、使用Process Explorer初步找到CPU占用高的原因 3、使用Clumsy工具在公司内网环境复现了问题 4、根据Process Explorer中的函数调用堆栈&#xff0c;分析源码&#xff0c;最终找出了问题 5、总结 在排查项目客户的视频图像闪烁问题时&#xff0c;无意中…

Centos7安装部署Jenkins

Jenkins简介&#xff1a; Jenkins只是一个平台&#xff0c;真正运作的都是插件。这就是jenkins流行的原因&#xff0c;因为jenkins什么插件都有 Hudson是Jenkins的前身&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控程序重复的工作&#xff0c;Hudson后来被…

JavaScript基础-02

常量&#xff08;字面量&#xff09;&#xff1a;数字和字符串 常量也称之为“字面量”&#xff0c;是固定值&#xff0c;不可改变。看见什么&#xff0c;它就是什么。 常量有下面这几种&#xff1a; 数字常量&#xff08;数值常量&#xff09;字符串常量布尔常量自定义常量…

【MATLAB数学建模编程实战】Kmeans算法编程及算法的简单原理

欢迎关注&#xff0c;本专栏主要更新MATLAB仿真、界面、基础编程、画图、算法、矩阵处理等操作&#xff0c;拥有丰富的实例练习代码&#xff0c;欢迎订阅该专栏&#xff01;&#xff08;等该专栏建设成熟后将开始收费&#xff0c;快快上车吧~~&#xff09; 【MATLAB数学建模编…

[LeetCode周赛复盘] 第 340 场周赛20230409

[LeetCode周赛复盘] 第 340 场周赛20230409 一、本周周赛总结二、 6361. 对角线上的质数1. 题目描述2. 思路分析3. 代码实现三、6360. 等值距离和1. 题目描述2. 思路分析3. 代码实现四、6359. 最小化数对的最大差值1. 题目描述2. 思路分析3. 代码实现五、 6353. 网格图中最少访…

ROS实践06 自定义消息类型

文章目录运行环境&#xff1a;思路&#xff1a;1.1 定义.msg文件1)功能包下新建 msg 目录&#xff0c;添加文件 Person.msg2)修改package.xml3)修改CMakeLists.txt2.1 自定义消息调用(C)1&#xff09;编译后修改includePath2&#xff09;发布方实现2.1修改CMakeLists.txt2.3运行…

【OpenCV-Python】cvui 之 trackbar

CVUI 之 trackbar cvui::trackbar() 渲染一个 trackbar&#xff0c; 可以左右拖动或点击对数字进行增加或减少的调整。 不使用离散间隔 使用离散间隔 Python import numpy as np import cv2 import cvuidef trackbar_test():WINDOW_NAME Trackbar-Test# 创建画布frame np.z…

【Python童年游戏】满满的回忆杀—那些年玩过的童年游戏你还记得吗?那个才是你的菜?看到第一个我就泪奔了(致我们逝去的青春)

导语 滴一一学生卡&#x1f64c; 结伴上车的学生仔子们 用笑声打破车厢的沉默 大人眼里的晚高峰 是给放学后快乐&#x1f600;时光的加时 下车的学生匆匆起身带起 一阵熟悉的栀子香于&#x1f493; 是关于校园的记忆 开始零零散散地闪现 放学后集合的秘密基地/跟着城…

LVGL v8学习笔记 |12 - 移植LVGL 8.3到ESP32C3开发板(ST7789)

一、移植前的准备 1. 基础工程 ESP32-IDF开发笔记 | 03 - 使用SPI外设驱动ST7789 SPILCD2. lvgl源码 https://github.com/lvgl/lvgl下载最新发布的 8.3.6 版本:https://github.com/lvgl/lvgl/releases/ 二、移植lvgl 1. 复制lvgl源码到工程中 将下载的 lvgl-8.3.6 文件夹直…

JSON数据遍历之for-in

JSON数据遍历之for-in object 本身就是无对象的集合&#xff0c;因此在用 for-in 语句遍历对象的属性时&#xff0c;遍历出的属性顺序与对象定义时不同。 W3C标准 根据 ECMA-262&#xff08;ECMAScript&#xff09;第三版中描述&#xff0c;for-in 语句的属性遍历的顺序是由对…

KlayGE-001-简介

KlayGE 引擎学习-001 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWlSlet9-1680688988724)(images/KlayGE_logo.png)] 一、KlayGE引擎介绍 软件简介 KlayGE中文译为&#xff1a;粘土游戏引擎&#xff0c;是一个开源、跨平台&#xff0c;基于插…

6-MATLAB APP Design-表格组件(uitable)

此博文通过MATLAB APP Design实现对学生成绩的处理,具体的功能包括读取表格数据、添加学生数据、计算总成绩、成绩排序+以及表格的保存。 一、APP 界面设计展示 1. 在画布中拖入面板、表格和四个按钮,布局如下。将面板的title写为“学生成绩计算器”并居中,将四个按钮的t…

游戏开发之Unity2021熟悉基本工具

接上一节通用渲染管线项目搭建 导入天空盒素材&#xff1a;在窗口中选择资源商店后会弹出下面的图片&#xff0c;在资源商店中找到我们想要的天空盒素材&#xff0c;将素材在unity中打开&#xff0c;如下面的第二幅图中就是我选择的天空盒素材&#xff0c;在这里可能会遇到一个…

Centos7搭建Ngrok内网穿透

一、安装gcc和git(用于下载ngrok源码) yum install gcc -y yum install git -y 二、安装go语言环境 yum install -y mercurial git bzr subversion golang golang-pkg-windows-amd64 golang-pkg-windows-386 三、检查环境安装 git --version //( > 1.7 ) go version 四…

通读《技术管理实战36讲》1、自我倾听篇

你好&#xff0c;我是小Z&#xff0c;一个工作在交付前线的程序员&#xff0c;我们正在通读《技术管理实战36讲》&#xff0c;作者刘建国。今天我们要梳理的章节是“自我倾听篇”。 在第1篇《多年前的那些工程师都去哪了&#xff1f;》中&#xff0c; 作者借助上周的“老知道人…

linux系统中cat命令的详细用法

在Linux中&#xff0c;cat命令是一个很常用的命令&#xff0c;它的作用是将文件内容输出到屏幕上&#xff0c;或者将多个文件合并成一个文件。下面是cat命令的一些常用用法&#xff1a; ​1. 显示文件内容 使用cat命令可以打印出文件的内容&#xff0c;如&#xff1a; cat fi…

[Qt 教程之Widgets模块] —— QFormLayout表单布局

Qt系列教程总目录 文章目录一、创建QFormLayout二、成员函数2.1. 对行操作2.2. 操作布局项2.3. 间距2.4. 设置布局规则2.5. 对齐方式表单布局 QFormLayout 以两列形式布局其子项。左列由标签组成&#xff0c;右列由小部件&#xff08;行编辑器、数字调整框等&#xff09;组成。…

FPGA实现图像去雾 基于暗通道先验算法 纯verilog代码加速 提供2套工程源码和技术支持

目录1、前言2、目前我这里已有的图像处理方案3、暗通道先验算法介绍4、本图像去雾模块的优缺点5、vivado工程详解vivado工程1详解vivado工程2详解6、上板调试验证7、福利&#xff1a;工程源码获取1、前言 本文详细描述了FPGA实现图像去雾的实现设计方案&#xff0c;采用暗通道…