关于Dart中的异步编程(dart异步原理)全程干货

随心笔谈2年前发布 admin
207 0 0

文章摘要

这篇文章主要介绍了Dart语言中的异步编程和相关概念。以下是文章的核心内容总结: 1. **Dart的事件循环和Root Isolate** - Dart的运行基于一个**Root Isolate**,所有程序在启动时都会有一个独立的事件循环。 - 事件循环从**mrcro队列**中取任务,处理完后进入**event队列**继续处理,且都是基于FIFO的队列结构。 2. **Future和异步编程的核心角色** - **Future**是Dart中用于封装一段延迟执行代码的核心抽象类,支持异步编程。 - Future用于返回异步操作的结果,注册回调时可以处理成功或失败的情况: - `then()`:处理成功结果 - `catchError()`:处理异常结果 - `whenComplete()`:在结果处理前后调用,无论结果如何都会被执行 3. **链式调用的优势** - 链式调用可以简化代码结构,解决回调地狱问题,同时支持多个依赖关系,避免嵌套调用。 - 示例展示了如何通过链式调用实现多次网络请求,代码逻辑清晰易懂。 4. **异步函数与`async-await`** - 在Dart中,使用`async`关键字定义异步函数,并配合`await`实现阻塞代码与非阻塞代码的调用。 - 大部分Future的使用场景都可以用`async-await`替代,并建议使用`async-await`简化代码。 5. **`isolate`与多线程资源利用** - Dart支持`isolate`,每个`isolate`独立运行,资源不共享,适合多核CPU环境。 - 示例展示了如何使用`Isolate` spawn实现异步操作,发送消息并处理回调。 6. **补充内容** - 文章还提到了Dart的异步编程生成器、自定义类型、多态控制反转等高级内容,以及Dart语法中的变量声明和数据类型。 总结来说,这篇文章通过实例和代码示例,全面讲解了Dart中的异步编程机制、事件循环工作原理以及如何利用`isolate`实现高效的多线程处理。



flutter 就是运行在一个root isolate 中

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

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

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

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

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() {

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() {

print(“main start”);
var res=getNetworkData();
print(res);
print(“main end”);
}

// 模拟网络请求
String getNetworkData() {
// 阻塞2秒
sleep(Duration(seconds: 2));
return “this is hello world”;
}

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

import ‘dart:io’;

main(List<String> args) {
print(“main start”);

// 这种方式可以解决回调地狱的问题 多个网络请求依赖也不用进行嵌套调用 直接链式调用即可
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”);
}

要定义异步函数,请在函数主体之前添加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 {
// 模拟三次网络请求

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

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

import ‘dart:io’;
import ‘dart:isolate’;

main(List<String> args) async {
print(“main start”);
// 1
ReceivePort 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);
// 收到结果 关闭 kill
receivePort.close();
isolate.kill();
});

print(“main end”);
}

calculate(SendPort port) {
// 模拟耗时操作
sleep(Duration(seconds: 2));
// 回调信息
port.send(“这是从创建的isolate 发送的信息”);
}

到此这篇关于关于Dart中的异步编程的文章就介绍到这了,更多相关Dart中的异步内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:vue-element-admin中node-sass换成dart-sass,安装依赖报code?128多种问题的解决方法SafeList?in?Flutter?and?Dart小技巧Dart多态控制反转编码规范实例详解Dart?异步编程生成器及自定义类型用法详解Dart语法之变量声明与数据类型实例详解Flutter入门学习Dart语言变量及基本使用概念

© 版权声明

相关文章